home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / sun / volume1 / calentool / part08 < prev    next >
Encoding:
Internet Message Format  |  1989-05-27  |  96.7 KB

  1. Path: uunet!cs.utexas.edu!rutgers!aramis.rutgers.edu!dartagnan.rutgers.edu!mcgrew
  2. From: mcgrew@dartagnan.rutgers.edu (Charles Mcgrew)
  3. Newsgroups: comp.sources.sun
  4. Subject: v01i017:  Calendar/planning tool: Part 08/09
  5. Message-ID: <May.27.17.15.04.1989.19355@dartagnan.rutgers.edu>
  6. Date: 27 May 89 21:15:07 GMT
  7. Organization: Rutgers Univ., New Brunswick, N.J.
  8. Lines: 3257
  9. Approved: mcgrew@aramis.rutgers.edu
  10.  
  11. Submitted-by: Bill Randle <billr@saab.cna.tek.com>
  12. Posting-number: Volume 1, Issue 17
  13. Archive-name: calentool/part08
  14.  
  15. #! /bin/sh
  16. # This is a shell archive, meaning:
  17. # 1. Remove everything above the #! /bin/sh line.
  18. # 2. Save the resulting text in a file.
  19. # 3. Execute the file with /bin/sh (not csh) to create the files:
  20. #    std.icon
  21. #    sunny.icon
  22. #    tool.c
  23. #    utils.c
  24. #    version.c
  25. #    week.cursor
  26. #    wevent.c
  27. #    wpaint.c
  28. #    year.cursor
  29. #    ypaint.c
  30. # This archive created: Sat May 27 13:14:18 1989
  31. export PATH; PATH=/bin:$PATH
  32. echo shar: extracting "'std.icon'" '(2591 characters)'
  33. if test -f 'std.icon'
  34. then
  35.     echo shar: will not over-write existing file "'std.icon'"
  36. else
  37. sed 's/^    X//' << \SHAR_EOF > 'std.icon'
  38.     X/* Format_version=1, Width=64, Height=64, Depth=1, Valid_bits_per_item=16
  39.     X *
  40.     X * $Header: std.icon,v 2.1 89/05/09 14:30:54 billr Exp $
  41.     X *      Copyright (C) 1988, The Regents of the University of California
  42.     X *                            All rights Reserved
  43.     X *                       Author: R. P. C. Rodgers, M.D.
  44.     X *
  45.     X * Redistribution and use in source and binary forms are permitted
  46.     X * provided that this notice is preserved and that due credit is given
  47.     X * to the University of California at San Francisco. The name of the University
  48.     X * may not be used to endorse or promote products derived from this
  49.     X * software without specific prior written permission. This software
  50.     X * is provided ``as is'' without express or implied warranty.
  51.     X */
  52.     X    0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x8000,0x0000,0x0000,0x0001,
  53.     X    0x8000,0x0000,0x0000,0x0001,0x8000,0x1800,0x0400,0x0181,
  54.     X    0x81C6,0x0862,0x8F18,0x6081,0x8201,0x0893,0x4424,0x9081,
  55.     X    0x8207,0x08E2,0x4424,0x9081,0x8209,0x0882,0x4424,0x9081,
  56.     X    0x81C5,0x0872,0x4318,0x6081,0x8000,0x0000,0x0000,0x0001,
  57.     X    0x8000,0x0001,0xE000,0x0001,0x8000,0x0007,0xF800,0x0001,
  58.     X    0x8000,0x000C,0x0C00,0x0001,0x8000,0x0018,0x0600,0x0001,
  59.     X    0x83FF,0xFFDB,0x36FF,0xFFF1,0x8600,0x0019,0x6600,0x0011,
  60.     X    0x8E00,0x0019,0xA600,0x0011,0x9A00,0x0019,0x2600,0x0011,
  61.     X    0x9200,0x0019,0x6600,0x0011,0x963F,0xFE19,0xA61F,0xFF11,
  62.     X    0x9A00,0x0019,0x2600,0x0011,0x9200,0x003D,0x6F00,0x0011,
  63.     X    0x963F,0xFE3D,0xAF1F,0xFF11,0x9A00,0x003D,0x2F00,0x0011,
  64.     X    0x9200,0x0019,0x6600,0x0011,0x963F,0xFE01,0xA01F,0xFF11,
  65.     X    0x9A00,0x0001,0x2000,0x0011,0x9200,0x0001,0x6000,0x0011,
  66.     X    0x963F,0xFE01,0xA01F,0xFF11,0x9A00,0x0001,0x2000,0x0011,
  67.     X    0x9200,0x0001,0x6000,0x0011,0x963F,0xFE00,0x001F,0xFF11,
  68.     X    0x9A00,0x0001,0xE000,0x0011,0x9200,0x0007,0xF800,0x0011,
  69.     X    0x963F,0xFE0C,0x0C1F,0xFF11,0x9A00,0x0019,0xA600,0x0011,
  70.     X    0x9200,0x0019,0x2600,0x0011,0x963F,0xFE19,0x661F,0xFF11,
  71.     X    0x9A00,0x0019,0xA600,0x0011,0x9200,0x0019,0x2600,0x0011,
  72.     X    0x963F,0xFE19,0x661F,0xFF11,0x9A00,0x0019,0xA600,0x0011,
  73.     X    0x9200,0x0019,0x2600,0x0011,0x963F,0xFE3D,0x6F1F,0xFF11,
  74.     X    0x9A00,0x003D,0xAF00,0x0011,0x9200,0x003D,0x2F00,0x0011,
  75.     X    0x9600,0x0019,0x6600,0x0011,0x9A00,0x0001,0xA000,0x0011,
  76.     X    0x9200,0x0001,0x2000,0x0011,0x9600,0x0001,0x6000,0x0011,
  77.     X    0x9A00,0x0001,0xA000,0x0011,0x9200,0x0001,0x2000,0x0011,
  78.     X    0x9600,0x0001,0x6000,0x0011,0x9A00,0x0001,0xA000,0x0011,
  79.     X    0x9200,0x0001,0x2000,0x0011,0x9600,0x0001,0x6000,0x0011,
  80.     X    0x9A00,0x0001,0xA000,0x0011,0x93FF,0xFFFF,0x3FFF,0xFFF1,
  81.     X    0x9649,0x2492,0x4924,0x9261,0x9C92,0x4924,0x9249,0x24C1,
  82.     X    0x9FFF,0xFFFF,0xFFFF,0xFF81,0x8000,0x0000,0x0000,0x0001,
  83.     X    0x8000,0x0000,0x0000,0x0001,0xFFFF,0xFFFF,0xFFFF,0xFFFF
  84. SHAR_EOF
  85. if test 2591 -ne "`wc -c < 'std.icon'`"
  86. then
  87.     echo shar: error transmitting "'std.icon'" '(should have been 2591 characters)'
  88. fi
  89. fi # end of overwriting check
  90. echo shar: extracting "'sunny.icon'" '(2593 characters)'
  91. if test -f 'sunny.icon'
  92. then
  93.     echo shar: will not over-write existing file "'sunny.icon'"
  94. else
  95. sed 's/^    X//' << \SHAR_EOF > 'sunny.icon'
  96.     X/* Format_version=1, Width=64, Height=64, Depth=1, Valid_bits_per_item=16
  97.     X *
  98.     X * $Header: sunny.icon,v 2.1 89/05/09 14:30:58 billr Exp $
  99.     X *      Copyright (C) 1989, The Regents of the University of California
  100.     X *                            All rights Reserved
  101.     X *                       Author: R. P. C. Rodgers, M.D.
  102.     X *
  103.     X * Redistribution and use in source and binary forms are permitted
  104.     X * provided that this notice is preserved and that due credit is given
  105.     X * to the University of California at San Francisco. The name of the University
  106.     X * may not be used to endorse or promote products derived from this
  107.     X * software without specific prior written permission. This software
  108.     X * is provided ``as is'' without express or implied warranty.
  109.     X */
  110.     X    0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x8001,0x0000,0x8800,0x0041,
  111.     X    0x8840,0x9020,0x8844,0x0881,0x8840,0x9120,0x8848,0x0881,
  112.     X    0x8420,0x4924,0x8848,0x1101,0x8220,0x4924,0x8A88,0x1101,
  113.     X    0x8210,0x4914,0x9290,0x2205,0x8111,0x2494,0x9290,0x2209,
  114.     X    0x8089,0x2494,0x9292,0x4409,0x8044,0x9494,0x9512,0x4811,
  115.     X    0xA044,0x9294,0x9524,0x8821,0x9222,0x5252,0x9524,0x9041,
  116.     X    0x8912,0x4A52,0x9529,0x1241,0x8491,0x2A4A,0x9549,0x2489,
  117.     X    0x8289,0x255F,0xFE4A,0x4511,0xA244,0x95EA,0x83D2,0x4A21,
  118.     X    0x9124,0x5720,0x02B4,0x9241,0x8892,0x7A00,0x000E,0x9481,
  119.     X    0x8449,0x6800,0x0009,0x2881,0x8225,0xA000,0x0001,0xD101,
  120.     X    0x8116,0x8000,0x0000,0xA221,0x808E,0x0000,0x0000,0x3443,
  121.     X    0x846C,0x0000,0x0000,0x088D,0xE210,0x01E0,0x03C0,0x1511,
  122.     X    0x91A8,0x8610,0x0430,0x8221,0x8C40,0x7808,0x000F,0x01C1,
  123.     X    0x82A0,0x00C4,0x0980,0x0185,0xE180,0x01E4,0x0BE0,0x0059,
  124.     X    0x9940,0x07E4,0x0BF0,0x0061,0x8600,0x0000,0x0800,0x0027,
  125.     X    0xE504,0x07C0,0x09F8,0x0119,0x9C21,0x0000,0x0400,0x0431,
  126.     X    0x8604,0x0000,0x0200,0x0093,0x8810,0x8028,0x0900,0x120D,
  127.     X    0xC944,0x8028,0x0900,0x14A9,0xBC22,0x8028,0x0900,0x1005,
  128.     X    0x9000,0x8018,0x0A00,0x114F,0x90C9,0x0004,0x3000,0x1805,
  129.     X    0xF003,0xC003,0xC000,0x6605,0xA828,0x3000,0x0003,0x807F,
  130.     X    0xA000,0x0E00,0x000C,0x01EB,0xA7E0,0x01E0,0x00F0,0x0355,
  131.     X    0xBEBC,0x001F,0xFF00,0x06AB,0xD5D7,0x8000,0x0000,0x0D55,
  132.     X    0xAAAA,0xE000,0x0000,0x1BAB,0xD555,0x5800,0x0700,0x355D,
  133.     X    0xAEAA,0xAE00,0xF800,0x6AAB,0xD555,0x7500,0x0000,0xD55D,
  134.     X    0xAAAB,0xAAC0,0x0001,0xAAAB,0xD555,0x5570,0x0003,0x5555,
  135.     X    0xBAAB,0xAAA8,0x0006,0xAABB,0xD577,0xD554,0x000D,0x5755,
  136.     X    0xAAAA,0xAAAA,0x001A,0xEAAB,0xD755,0x5D55,0x0075,0x5755,
  137.     X    0xABAA,0xAAEA,0xE1EB,0xAFAB,0xD755,0x5555,0x5F55,0x5555,
  138.     X    0xAFAB,0xAAEA,0xBAAA,0xAAAB,0xD7D5,0x5557,0x5755,0x5555,
  139.     X    0xAFAA,0xAAAA,0xABEA,0xABAB,0xDFD5,0x5555,0x555D,0x555D,
  140.     X    0xAAAA,0xAEAE,0xBABB,0xAAAB,0xD555,0x5555,0x5557,0x755D,
  141.     X    0xAAAA,0xAEAA,0xAAAA,0xAABF,0xFFFF,0xFFFF,0xFFFF,0xFFFF
  142. SHAR_EOF
  143. if test 2593 -ne "`wc -c < 'sunny.icon'`"
  144. then
  145.     echo shar: error transmitting "'sunny.icon'" '(should have been 2593 characters)'
  146. fi
  147. fi # end of overwriting check
  148. echo shar: extracting "'tool.c'" '(30604 characters)'
  149. if test -f 'tool.c'
  150. then
  151.     echo shar: will not over-write existing file "'tool.c'"
  152. else
  153. sed 's/^    X//' << \SHAR_EOF > 'tool.c'
  154.     X/*
  155.     X * $Header: tool.c,v 2.1 89/05/09 14:23:08 billr Exp $
  156.     X */
  157.     X/*
  158.     X * tool.c
  159.     X *
  160.     X * Author: Philip Heller, Sun Microsystems. Inc. <terrapin!heller@sun.com>
  161.     X *
  162.     X * Original source Copyright (C) 1987, Sun Microsystems, Inc.
  163.     X *    All Rights Reserved
  164.     X * Permission is hereby granted to use and modify this program in source
  165.     X * or binary form as long as it is not sold for profit and this copyright
  166.     X * notice remains intact.
  167.     X *
  168.     X *
  169.     X * Changes/additions by: Bill Randle, Tektronix, Inc. <billr@saab.CNA.TEK.COM>
  170.     X *
  171.     X * Changes and additions Copyright (C) 1988, 1989 Tektronix, Inc.
  172.     X *    All Rights Reserved
  173.     X * Permission is hereby granted to use and modify the modifications in source
  174.     X * or binary form as long as they are not sold for profit and this copyright
  175.     X * notice remains intact.
  176.     X */
  177.     X#include <stdio.h>    /* for NULL */
  178.     X#include <suntool/sunview.h>
  179.     X#include <suntool/canvas.h>
  180.     X#include <suntool/panel.h>
  181.     X#include <sunwindow/defaults.h>
  182.     X#include <sys/file.h>
  183.     X#include "ct.h"
  184.     X
  185.     Xextern struct tm current;
  186.     Xextern Frame frame;
  187.     Xextern int working_msg;
  188.     XCanvas canvas;
  189.     XPanel panel;
  190.     XPanel_item todaybutton_pi, working_pi;
  191.     XPanel_item monthmenu_pi, yearmenu_pi, weekbutton_pi, daybutton_pi;
  192.     XPanel_item previous_pi, next_pi, current_pi, filebutton_pi;
  193.     XPanel_item clock_pi;
  194.     X#ifndef NO_PRINTER
  195.     XPanel_item printbutton_pi;
  196.     X#endif
  197.     X#ifndef NO_SUN_MOON
  198.     XPanel_item moonbutton_pi, sunbutton_pi;
  199.     X#endif
  200.     XMenu next_menu, previous_menu;
  201.     XMenu day_menu, week_menu, month_menu, year_menu;
  202.     XMenu day_sel_menu, current_menu;
  203.     X#ifndef NO_PRINTER
  204.     XMenu print_menu;
  205.     X#endif
  206.     XPixfont *font, *bigfont, *sfont;
  207.     XFrame fframe = 0;
  208.     XPanel fpanel, fcpanel;
  209.     XFrame attr_frame;
  210.     XPanel attr_panel;
  211.     XPanel_item repeat_pi, remind_pi, everyx_pi, whichwk_pi, marked_pi;
  212.     XFrame del_frame;
  213.     XPanel del_panel;
  214.     XPanel_item del_choice_pi;
  215.     XFrame wmore_frame;
  216.     XPanel wmore_panel;
  217.     X#ifndef NO_SUN_MOON
  218.     XFrame sframe = 0, mframe = 0;
  219.     X#endif
  220.     XFrame fileframe;
  221.     XPanel filepanel;
  222.     XPanel_item filename_pi, file_ro_pi;
  223.     X#ifndef NO_PRINTER
  224.     XPanel_item prcmd_pi;
  225.     XFrame prframe;
  226.     X#endif
  227.     X#ifndef NO_SUN_MOON
  228.     XCanvas scanvas, mcanvas;
  229.     XPanel_item sdate_pi, mdate_pi;
  230.     X#endif
  231.     XFrame prompt_frame = 0;
  232.     XPixrect *morebutton;
  233.     Xstatic Cursor panel_cursor, canvas_cursor;
  234.     XFrame date_frame;
  235.     XPanel_item setdate_pi;
  236.     XFrame cut_frame;
  237.     XPanel cut_panel;
  238.     Xvoid monthmenu_notify(), yearmenu_notify(), weekbutton_notify();
  239.     Xvoid month_menu_event(), year_menu_event(), week_menu_event();
  240.     Xvoid todaybutton_notify(), currentbutton_notify(), daybutton_notify();
  241.     Xvoid filebutton_notify(), current_menu_event();
  242.     Xvoid cut_done(), cut_abort();
  243.     X#ifndef NO_SUN_MOON
  244.     Xvoid moonbutton_notify(), sunbutton_notify();
  245.     X#endif
  246.     X#ifndef NO_PRINTER
  247.     Xvoid printbutton_notify(), print_menu_event();
  248.     X#endif
  249.     Xvoid day_menu_event();
  250.     Xvoid mainsw_selected();
  251.     Xvoid next_menu_event(), nextbutton_notify();
  252.     Xvoid previous_menu_event(), previous_menu_notify();
  253.     Xvoid mainsw_inputevent();
  254.     Xvoid fdone_proc(), fkeep_proc(), fappt_notify();
  255.     Xvoid attr_accept(), attr_abort();
  256.     Xvoid del_done();
  257.     X#ifndef NO_SUN_MOON
  258.     Xvoid sdone_proc(), mdone_proc();
  259.     Xvoid sframe_done(), mframe_done();
  260.     X#endif
  261.     Xvoid fileframe_done(), file_accept(), file_reset(), file_done();
  262.     Xvoid file_save();
  263.     Xvoid prompt_no_notify(), prompt_yes_notify();
  264.     Xvoid error_event(), file_orig();
  265.     Xvoid dtframe_done(), dtdone_proc();
  266.     X#ifndef NO_PRINTER
  267.     Xvoid prframe_done(), prdone_proc();
  268.     X#endif
  269.     XNotify_value check_close();
  270.     Xint monthlength();
  271.     Xchar year_str[NR_YEARS][5]; /* holds strings for year menu */
  272.     Xextern Pixwin *main_pixwin;
  273.     Xextern Cursor day_cursor, wait_cursor;
  274.     Xextern int day_is_open, mainsw_state;
  275.     Xextern char todays_date[];
  276.     Xextern struct appt_entry future[];
  277.     Xextern int findex;
  278.     Xextern struct dayslot slots[];
  279.     X#ifndef NO_SUN_MOON
  280.     Xextern Pixrect moon_icon_pr, sun_icon_pr;
  281.     X#endif
  282.     Xextern char printer[];
  283.     X
  284.     X/* Create and init control panel */
  285.     Xcreate_panel()
  286.     X{
  287.     X    int    width;
  288.     X
  289.     X    /* Create the control panel. */
  290.     X    panel = window_create(frame, PANEL,
  291.     X              WIN_HEIGHT, 72, WIN_FONT, font,
  292.     X              WIN_CONSUME_KBD_EVENTS,
  293.     X              WIN_UP_EVENTS, KEY_LEFT(7), 0,
  294.     X              WIN_ERROR_MSG, "Can't create main panel.",
  295.     X              0);
  296.     X
  297.     X    /* Create the panel items and their menus */
  298.     X    day_menu = menu_create(MENU_STRINGS,
  299.     X            "Sunday", "Monday", "Tuesday", "Wednesday",
  300.     X            "Thursday", "Friday", "Saturday", 0,
  301.     X            0);
  302.     X
  303.     X    daybutton_pi = panel_create_item(panel, PANEL_BUTTON,
  304.     X                        PANEL_LABEL_IMAGE, 
  305.     X                          panel_button_image(panel, "Day", 4, font),
  306.     X            PANEL_EVENT_PROC, day_menu_event,
  307.     X                        PANEL_NOTIFY_PROC, daybutton_notify,
  308.     X            PANEL_ITEM_X, ATTR_COL(2),
  309.     X            PANEL_ITEM_Y, ATTR_ROW(0)+2,
  310.     X                        0);
  311.     X    
  312.     X    week_menu = menu_create(MENU_STRINGS, "1st", "2nd",
  313.     X            "3rd", "4th", "5th", "Last", 0,
  314.     X            0);
  315.     X
  316.     X    weekbutton_pi = panel_create_item(panel, PANEL_BUTTON,
  317.     X                        PANEL_LABEL_IMAGE, 
  318.     X                          panel_button_image(panel, "Week", 5, font),
  319.     X            PANEL_EVENT_PROC, week_menu_event,
  320.     X                        PANEL_NOTIFY_PROC, weekbutton_notify,
  321.     X            PANEL_ITEM_X, ATTR_COL(8),
  322.     X            PANEL_ITEM_Y, ATTR_ROW(0)+2,
  323.     X                        0);
  324.     X
  325.     X    month_menu = menu_create(MENU_STRINGS,
  326.     X            "January", "February","March",
  327.     X            "April", "May", "June", "July", "August",
  328.     X            "September", "October", "November", "December", 0,
  329.     X            0);
  330.     X
  331.     X    monthmenu_pi = panel_create_item(panel, PANEL_BUTTON,  
  332.     X                        PANEL_LABEL_IMAGE,
  333.     X              panel_button_image(panel, "Month", 6, font),
  334.     X            PANEL_EVENT_PROC, month_menu_event,
  335.     X                        PANEL_NOTIFY_PROC, monthmenu_notify,  
  336.     X            PANEL_ITEM_X, ATTR_COL(15),
  337.     X            PANEL_ITEM_Y, ATTR_ROW(0)+2,
  338.     X                        0);
  339.     X
  340.     X    year_menu = menu_create(0);    /* years filled in later */
  341.     X    add_years_to_menu();
  342.     X
  343.     X    yearmenu_pi = panel_create_item(panel, PANEL_BUTTON,
  344.     X                        PANEL_LABEL_IMAGE,
  345.     X              panel_button_image(panel, "Year", 5, font),
  346.     X            PANEL_EVENT_PROC, year_menu_event,
  347.     X                        PANEL_NOTIFY_PROC, yearmenu_notify,
  348.     X            PANEL_ITEM_X, ATTR_COL(23),
  349.     X            PANEL_ITEM_Y, ATTR_ROW(0)+2,
  350.     X                        0);
  351.     X
  352.     X    todaybutton_pi = panel_create_item(panel, PANEL_BUTTON,
  353.     X                        PANEL_LABEL_IMAGE, 
  354.     X                          panel_button_image(panel, "Today", 6, font),
  355.     X                        PANEL_NOTIFY_PROC, todaybutton_notify,
  356.     X            PANEL_ITEM_X, ATTR_COL(33),
  357.     X            PANEL_ITEM_Y, ATTR_ROW(0)+2,
  358.     X                        0);
  359.     X
  360.     X    filebutton_pi = panel_create_item(panel, PANEL_BUTTON,
  361.     X                        PANEL_LABEL_IMAGE, 
  362.     X                          panel_button_image(panel, "File", 5, font),
  363.     X                        PANEL_NOTIFY_PROC, filebutton_notify,
  364.     X            PANEL_ITEM_X, ATTR_COL(45),
  365.     X            PANEL_ITEM_Y, ATTR_ROW(0)+2,
  366.     X                        0);
  367.     X
  368.     X#ifndef NO_PRINTER
  369.     X    printbutton_pi = panel_create_item(panel, PANEL_BUTTON,
  370.     X                        PANEL_LABEL_IMAGE, 
  371.     X                          panel_button_image(panel, "Print", 6, font),
  372.     X                        PANEL_EVENT_PROC, print_menu_event,
  373.     X                        PANEL_NOTIFY_PROC, printbutton_notify,
  374.     X            PANEL_ITEM_X, ATTR_COL(53),
  375.     X            PANEL_ITEM_Y, ATTR_ROW(0)+2,
  376.     X            PANEL_SHOW_ITEM, FALSE,
  377.     X                        0);
  378.     X    
  379.     X    print_menu = menu_create(MENU_STRINGS, "Print Postscript", "Print Raster",
  380.     X            "Change Printer", 0,
  381.     X            0);
  382.     X#endif
  383.     X
  384.     X    working_pi = panel_create_item(panel, PANEL_MESSAGE,
  385.     X            PANEL_LABEL_STRING, "Working!",
  386.     X            PANEL_LABEL_FONT, font,
  387.     X            PANEL_LABEL_BOLD, TRUE,
  388.     X            PANEL_SHOW_ITEM, FALSE,
  389.     X            PANEL_ITEM_X, ATTR_COL(37),
  390.     X            PANEL_ITEM_Y, ATTR_ROW(1)+5,
  391.     X            0);
  392.     X
  393.     X    previous_menu = menu_create(MENU_STRINGS,
  394.     X            "Yesterday", "Last Week", "Last Month", "Last Year", 0,
  395.     X            0);
  396.     X    
  397.     X    previous_pi = panel_create_item(panel, PANEL_BUTTON,
  398.     X                        PANEL_LABEL_IMAGE, 
  399.     X                          panel_button_image(panel, "Previous", 9, font),
  400.     X            PANEL_EVENT_PROC, previous_menu_event,
  401.     X                        PANEL_NOTIFY_PROC, previous_menu_notify, 
  402.     X            PANEL_ITEM_X, ATTR_COL(2),
  403.     X            PANEL_ITEM_Y, ATTR_ROW(2)-2,
  404.     X            0);
  405.     X
  406.     X    current_menu = menu_create(MENU_STRINGS, "Current Day",
  407.     X            "Current Week", "Current Month", "Current Year",
  408.     X            "Change Date", 0,
  409.     X            0);
  410.     X
  411.     X    current_pi = panel_create_item(panel, PANEL_BUTTON,
  412.     X                        PANEL_LABEL_IMAGE, 
  413.     X                          panel_button_image(panel, "Current", 8, font),
  414.     X            PANEL_EVENT_PROC, current_menu_event,
  415.     X                        PANEL_NOTIFY_PROC, currentbutton_notify,
  416.     X            PANEL_ITEM_X, ATTR_COL(13),
  417.     X            PANEL_ITEM_Y, ATTR_ROW(2)-2,
  418.     X                        0);
  419.     X
  420.     X    next_menu = menu_create(MENU_STRINGS,
  421.     X            "Tommorow", "Next Week", "Next Month", "Next Year", 0,
  422.     X            0);
  423.     X    
  424.     X    next_pi = panel_create_item(panel, PANEL_BUTTON,
  425.     X                        PANEL_LABEL_IMAGE, 
  426.     X                          panel_button_image(panel, "Next", 5, font),
  427.     X            PANEL_EVENT_PROC, next_menu_event,
  428.     X                        PANEL_NOTIFY_PROC, nextbutton_notify, 
  429.     X            PANEL_ITEM_X, ATTR_COL(23),
  430.     X            PANEL_ITEM_Y, ATTR_ROW(2)-2,
  431.     X            0);
  432.     X
  433.     X    width = (int)window_get(panel, WIN_WIDTH);
  434.     X
  435.     X    clock_pi = panel_create_item(panel, PANEL_MESSAGE,
  436.     X            PANEL_ITEM_X, width-150-(strlen(todays_date)*font->pf_defaultsize.x),
  437.     X            PANEL_ITEM_Y, ATTR_ROW(2)+3,
  438.     X            PANEL_LABEL_STRING, todays_date,
  439.     X            PANEL_LABEL_FONT, font,
  440.     X            0);
  441.     X
  442.     X#ifndef NO_SUN_MOON
  443.     X    sunbutton_pi = panel_create_item(panel, PANEL_BUTTON,
  444.     X                        PANEL_LABEL_IMAGE, &sun_icon_pr,
  445.     X                        PANEL_NOTIFY_PROC, sunbutton_notify,
  446.     X            PANEL_ITEM_X, width-140,
  447.     X            PANEL_ITEM_Y, ATTR_ROW(0),
  448.     X            PANEL_SHOW_ITEM, FALSE,
  449.     X                        0);
  450.     X
  451.     X    moonbutton_pi = panel_create_item(panel, PANEL_BUTTON,
  452.     X                        PANEL_LABEL_IMAGE, &moon_icon_pr,
  453.     X                        PANEL_NOTIFY_PROC, moonbutton_notify,
  454.     X            PANEL_ITEM_X, width-70,
  455.     X            PANEL_ITEM_Y, ATTR_ROW(0),
  456.     X            PANEL_SHOW_ITEM, FALSE,
  457.     X                        0);
  458.     X#endif
  459.     X
  460.     X    /*
  461.     X     * menu strings for right MB menu in the canvas
  462.     X     * (day display). NB: if the order of this menu is
  463.     X     * changed, also change the #defines in ct.h
  464.     X     * (MMODIFY, MCUT, etc.).
  465.     X     */
  466.     X    day_sel_menu = menu_create(MENU_STRINGS,
  467.     X            "Modify", "Cut", "Paste", "Copy", "Delete",
  468.     X            "Undelete", 0,
  469.     X            0);
  470.     X
  471.     X    /*
  472.     X     * this button is displayed in the canvas, but needs a panel
  473.     X     * for the function call to work properly
  474.     X     */
  475.     X    morebutton = panel_button_image(panel, "More", 4, font);
  476.     X
  477.     X    /*
  478.     X     * interpose on panel events to check for L7 (open/close)
  479.     X     */
  480.     X    notify_interpose_event_func(panel, check_close, NOTIFY_SAFE);
  481.     X}
  482.     X
  483.     X/*
  484.     X * Add year strings to year panel menu
  485.     X */
  486.     Xadd_years_to_menu()
  487.     X{
  488.     X    int n, year;
  489.     X
  490.     X    n = 1;
  491.     X    for (year=START_YEAR; year<START_YEAR+NR_YEARS; year++,n++) {
  492.     X        sprintf(year_str[n-1], "%4d", year+1900);
  493.     X        menu_set(year_menu, MENU_STRING_ITEM, year_str[n-1], n, 0);
  494.     X    }
  495.     X}
  496.     X
  497.     X/* turn sun and moon buttons on or off */
  498.     Xsun_moon_buttons(state)
  499.     Xint state;
  500.     X{
  501.     X#ifndef NO_SUN_MOON
  502.     X    if (state) {
  503.     X        if (!mframe)
  504.     X            panel_set(moonbutton_pi, PANEL_SHOW_ITEM, TRUE, 0);
  505.     X        if (!sframe)
  506.     X            panel_set(sunbutton_pi, PANEL_SHOW_ITEM, TRUE, 0);
  507.     X    } else {
  508.     X        panel_set(moonbutton_pi, PANEL_SHOW_ITEM, FALSE, 0);
  509.     X        panel_set(sunbutton_pi, PANEL_SHOW_ITEM, FALSE, 0);
  510.     X        /* remove moon window, if it exists */
  511.     X        if (mframe) {
  512.     X            window_destroy(mframe);
  513.     X            mframe = 0;
  514.     X        }
  515.     X        /* remove sun window, if it exists */
  516.     X        if (sframe) {
  517.     X            window_destroy(sframe);
  518.     X            sframe = 0;
  519.     X        }
  520.     X    }
  521.     X#endif
  522.     X}
  523.     X
  524.     X/* turn print button on or off */
  525.     Xprint_button(state)
  526.     Xint state;
  527.     X{
  528.     X#ifndef NO_PRINTER
  529.     X/* if no printer specified then never show Print button */
  530.     X    if (state)
  531.     X        panel_set(printbutton_pi, PANEL_SHOW_ITEM, TRUE, 0);
  532.     X    else
  533.     X        panel_set(printbutton_pi, PANEL_SHOW_ITEM, FALSE, 0);
  534.     X#endif    /* NO_PRINTER */
  535.     X}
  536.     X
  537.     Xworking(state)
  538.     Xint state;
  539.     X{
  540.     X    /* turn "Working!" message on or off */
  541.     X    if (working_msg) {
  542.     X        if (state)
  543.     X            panel_set(working_pi, PANEL_SHOW_ITEM, TRUE, 0);
  544.     X        else
  545.     X            panel_set(working_pi, PANEL_SHOW_ITEM, FALSE, 0);
  546.     X    }
  547.     X}
  548.     X
  549.     X/* Create and init main subwindow. */
  550.     Xcreate_main_window()
  551.     X{
  552.     X    canvas = window_create(frame, CANVAS,
  553.     X            CANVAS_FIXED_IMAGE, TRUE,
  554.     X            WIN_CONSUME_KBD_EVENTS, WIN_ASCII_EVENTS,
  555.     X            WIN_UP_EVENTS, KEY_LEFT(7), 0,
  556.     X            WIN_CONSUME_PICK_EVENTS, WIN_NO_EVENTS,
  557.     X            WIN_MOUSE_BUTTONS, LOC_STILL, LOC_DRAG,
  558.     X            WIN_IN_TRANSIT_EVENTS, 0,
  559.     X            WIN_EVENT_PROC, mainsw_inputevent,
  560.     X            CANVAS_RETAINED, TRUE,
  561.     X            WIN_BELOW, panel,
  562.     X            WIN_ERROR_MSG, "Can't create main window.",
  563.     X            0);
  564.     X    main_pixwin = (Pixwin *) canvas_pixwin(canvas);
  565.     X    
  566.     X    window_set(canvas, WIN_CURSOR, day_cursor, 0);
  567.     X    mainsw_state = DISPLAYING_DAY;
  568.     X    day_is_open = FALSE;
  569.     X    draw_day1();  /* like draw_day(), only no future popup */
  570.     X}
  571.     X
  572.     Xget_fonts()
  573.     X{
  574.     X    char *default_ptr, fontstr[128];
  575.     X
  576.     X    /* Open normal and big font files. */
  577.     X    if ((default_ptr = defaults_get_string("/CalenTool/Font", NULL, 0)) != NULL) {
  578.     X        if (*default_ptr != '/') {
  579.     X            strcpy(fontstr, "/usr/lib/fonts/fixedwidthfonts/");
  580.     X            strcat(fontstr, default_ptr);
  581.     X            if ((font = pf_open(fontstr)) == NULL)
  582.     X                font = pw_pfsysopen();
  583.     X        } else {
  584.     X            if ((font = pf_open(default_ptr)) == NULL)
  585.     X                font = pw_pfsysopen();
  586.     X        }
  587.     X    } else
  588.     X        font = pw_pfsysopen();
  589.     X    if ((default_ptr = defaults_get_string("/CalenTool/BigFont", NULL, 0)) != NULL) {
  590.     X        if (*default_ptr != '/') {
  591.     X            strcpy(fontstr, "/usr/lib/fonts/fixedwidthfonts/");
  592.     X            strcat(fontstr, default_ptr);
  593.     X            if ((bigfont = pf_open(fontstr)) == NULL)
  594.     X                bigfont = pf_open("/usr/lib/fonts/fixedwidthfonts/gallant.r.10");
  595.     X        } else {
  596.     X            if ((bigfont = pf_open(default_ptr)) == NULL)
  597.     X                bigfont = pf_open("/usr/lib/fonts/fixedwidthfonts/gallant.r.10");
  598.     X        }
  599.     X    } else
  600.     X        bigfont = pf_open("/usr/lib/fonts/fixedwidthfonts/gallant.r.10");
  601.     X    /* font for displaying time under the icon */
  602.     X    sfont = pf_open("/usr/lib/fonts/fixedwidthfonts/screen.r.7");
  603.     X}
  604.     X
  605.     X/*
  606.     X * create popup window for future appts display
  607.     X * called when we draw a day display.
  608.     X */
  609.     Xcreate_future_popup()
  610.     X{
  611.     X    int i, p_width;
  612.     X    Panel_item item;
  613.     X    char *fappt_str, *format_appt();
  614.     X    static Panel_item fdone_pi, fkeep_pi;
  615.     X    static int cp_width, cp_x;
  616.     X
  617.     X    if (!fframe) {
  618.     X        /* create new frame and control panel */
  619.     X        fframe = window_create(frame, FRAME, FRAME_NO_CONFIRM, TRUE,
  620.     X                WIN_SHOW, TRUE, WIN_X, ATTR_COL(12),
  621.     X                WIN_Y, slots[N_SLOTS-4].slot_pos.top,
  622.     X                FRAME_LABEL, "Future Appointments",
  623.     X                FRAME_SHOW_LABEL, TRUE,
  624.     X                WIN_ERROR_MSG, "Can't create future frame.",
  625.     X                0);
  626.     X
  627.     X        fcpanel = window_create(fframe, PANEL, 0);
  628.     X    
  629.     X        fkeep_pi = panel_create_item(fcpanel, PANEL_BUTTON, PANEL_NOTIFY_PROC,
  630.     X                fkeep_proc, PANEL_LABEL_IMAGE,
  631.     X                panel_button_image(fcpanel, "Keep", 4, font),
  632.     X                PANEL_SHOW_ITEM, TRUE,
  633.     X                PANEL_ITEM_X, ATTR_COL(20),
  634.     X                PANEL_ITEM_Y, ATTR_ROW(0),
  635.     X                0);
  636.     X    
  637.     X        fdone_pi = panel_create_item(fcpanel, PANEL_BUTTON, PANEL_NOTIFY_PROC,
  638.     X                fdone_proc, PANEL_LABEL_IMAGE,
  639.     X                panel_button_image(fcpanel, "Done", 4, font),
  640.     X                PANEL_SHOW_ITEM, TRUE,
  641.     X                PANEL_ITEM_X, ATTR_COL(30),
  642.     X                PANEL_ITEM_Y, ATTR_ROW(0),
  643.     X                0);
  644.     X    
  645.     X        window_fit(fcpanel);
  646.     X        cp_width = (int) window_get(fcpanel, WIN_WIDTH);
  647.     X        cp_x = (int) window_get(fcpanel, WIN_X);
  648.     X
  649.     X    } else {
  650.     X        /* existing frame, so just delete and recreate the
  651.     X         * message panel and its items
  652.     X         */
  653.     X        window_destroy(fpanel);
  654.     X    }
  655.     X    fpanel = window_create(fframe, PANEL, WIN_BELOW, fcpanel,
  656.     X            WIN_FONT, font, WIN_X, cp_x, 0);
  657.     X    /* create a panel message item for each future appt */
  658.     X    for (i=0; i<findex; i++) {
  659.     X        fappt_str = format_appt(&future[i]);
  660.     X        (void) panel_create_item(fpanel, PANEL_MESSAGE,
  661.     X                PANEL_NOTIFY_PROC, fappt_notify,
  662.     X                PANEL_SHOW_ITEM, TRUE,
  663.     X                PANEL_CLIENT_DATA, (caddr_t)i,
  664.     X                PANEL_LABEL_X, ATTR_COL(1),
  665.     X                PANEL_LABEL_Y, ATTR_ROW(i),
  666.     X                PANEL_LABEL_FONT, font,
  667.     X                PANEL_LABEL_STRING, fappt_str,
  668.     X                0);
  669.     X    }
  670.     X    window_fit(fpanel);
  671.     X    /* find out which panel is wider and use it for frame width */
  672.     X    p_width = (int) window_get(fpanel, WIN_WIDTH);
  673.     X    if (p_width > cp_width) {
  674.     X        /* reset control panel size */
  675.     X        window_set(fcpanel, WIN_WIDTH, p_width, 0);
  676.     X        /* move buttons */
  677.     X        panel_set(fdone_pi, PANEL_ITEM_X, ATTR_COL(-7)+p_width,
  678.     X                PANEL_SHOW_ITEM, TRUE,
  679.     X                0);
  680.     X        panel_set(fkeep_pi, PANEL_ITEM_X, ATTR_COL(-17)+p_width,
  681.     X                PANEL_SHOW_ITEM, TRUE,
  682.     X                0);
  683.     X    } else {
  684.     X        window_set(fpanel, WIN_WIDTH, cp_width, 0);
  685.     X        /* move buttons */
  686.     X        panel_set(fdone_pi, PANEL_ITEM_X, ATTR_COL(-7)+cp_width,
  687.     X                PANEL_SHOW_ITEM, TRUE,
  688.     X                0);
  689.     X        panel_set(fkeep_pi, PANEL_ITEM_X, ATTR_COL(-17)+cp_width,
  690.     X                PANEL_SHOW_ITEM, TRUE,
  691.     X                0);
  692.     X    }
  693.     X    window_fit(fframe);
  694.     X}
  695.     X
  696.     X/*
  697.     X * create a popup to modify or set attributes for a given
  698.     X * appointment.
  699.     X */
  700.     Xcreate_attr_frame()
  701.     X{
  702.     X    void everyx_notify();
  703.     X
  704.     X    /* create new frame and control panel */
  705.     X    attr_frame = window_create(frame, FRAME, FRAME_NO_CONFIRM, TRUE,
  706.     X            FRAME_SHOW_LABEL, FALSE,
  707.     X            WIN_ERROR_MSG, "Can't create attributes frame.",
  708.     X            0);
  709.     X
  710.     X    attr_panel = window_create(attr_frame, PANEL,
  711.     X            WIN_FONT, font,
  712.     X            PANEL_BLINK_CARET, TRUE,
  713.     X            0);
  714.     X    
  715.     X    (void) panel_create_item(attr_panel, PANEL_MESSAGE,
  716.     X            PANEL_SHOW_ITEM, TRUE,
  717.     X            PANEL_LABEL_STRING, "Appointment Options",
  718.     X            PANEL_LABEL_X, ATTR_COL(4),
  719.     X            PANEL_LABEL_Y, ATTR_ROW(0)+4,
  720.     X            PANEL_LABEL_BOLD, TRUE,
  721.     X            0);
  722.     X
  723.     X    (void) panel_create_item(attr_panel, PANEL_BUTTON, PANEL_NOTIFY_PROC,
  724.     X            attr_accept, PANEL_LABEL_IMAGE,
  725.     X            panel_button_image(attr_panel, "Accept", 6, font),
  726.     X            PANEL_SHOW_ITEM, TRUE,
  727.     X            PANEL_ITEM_X, ATTR_COL(35),
  728.     X            PANEL_ITEM_Y, ATTR_ROW(0),
  729.     X            0);
  730.     X
  731.     X    (void) panel_create_item(attr_panel, PANEL_BUTTON, PANEL_NOTIFY_PROC,
  732.     X            attr_abort, PANEL_LABEL_IMAGE,
  733.     X            panel_button_image(attr_panel, "Abort", 5, font),
  734.     X            PANEL_SHOW_ITEM, TRUE,
  735.     X            PANEL_ITEM_X, ATTR_COL(45),
  736.     X            PANEL_ITEM_Y, ATTR_ROW(0),
  737.     X            0);
  738.     X
  739.     X    everyx_pi = panel_create_item(attr_panel, PANEL_TOGGLE,
  740.     X            PANEL_SHOW_ITEM, TRUE,
  741.     X            PANEL_DISPLAY_LEVEL, PANEL_ALL,
  742.     X            PANEL_NOTIFY_PROC, everyx_notify,
  743.     X            PANEL_LABEL_STRING, "Repeat appointment:",
  744.     X            PANEL_CHOICE_STRINGS, "Every Day", "Selected Week",
  745.     X            "Every Month", "Every Year", 0,
  746.     X            PANEL_ITEM_X, ATTR_COL(1),
  747.     X            PANEL_ITEM_Y, ATTR_ROW(2)-5,
  748.     X            0);
  749.     X
  750.     X    whichwk_pi = panel_create_item(attr_panel, PANEL_TOGGLE,
  751.     X            PANEL_SHOW_ITEM, TRUE,
  752.     X            PANEL_DISPLAY_LEVEL, PANEL_ALL,
  753.     X            PANEL_LABEL_STRING,
  754.     X            "Indicate which week(s) in the month:",
  755.     X            PANEL_CHOICE_STRINGS, "1st", "2nd",
  756.     X            "3rd", "4th", "5th", "Last", 0,
  757.     X            PANEL_ITEM_X, ATTR_COL(1),
  758.     X            PANEL_ITEM_Y, ATTR_ROW(3)-5,
  759.     X            0);
  760.     X
  761.     X    repeat_pi = panel_create_item(attr_panel, PANEL_TEXT,
  762.     X            PANEL_SHOW_ITEM, FALSE,
  763.     X            PANEL_LABEL_STRING,
  764.     X            "Repeat at specified interval of days:",
  765.     X            PANEL_VALUE, 0, PANEL_VALUE_STORED_LENGTH, 4,
  766.     X            PANEL_VALUE_DISPLAY_LENGTH, 4,
  767.     X            PANEL_ITEM_X, ATTR_COL(1),
  768.     X            PANEL_ITEM_Y, ATTR_ROW(3),
  769.     X            PANEL_BLINK_CARET, TRUE,
  770.     X            0);
  771.     X    
  772.     X    remind_pi = panel_create_item(attr_panel, PANEL_TEXT,
  773.     X            PANEL_SHOW_ITEM, TRUE,
  774.     X            PANEL_LABEL_STRING,
  775.     X            "Warn in advance by specified number of days:",
  776.     X            PANEL_VALUE, 0, PANEL_VALUE_STORED_LENGTH, 4,
  777.     X            PANEL_VALUE_DISPLAY_LENGTH, 4,
  778.     X            PANEL_ITEM_X, ATTR_COL(1),
  779.     X            PANEL_ITEM_Y, ATTR_ROW(4),
  780.     X            PANEL_BLINK_CARET, TRUE,
  781.     X            0);
  782.     X
  783.     X    /* This panel item is currently only supported
  784.     X     * for note appointment entries.
  785.     X     */
  786.     X    marked_pi = panel_create_item(attr_panel, PANEL_CYCLE,
  787.     X            PANEL_SHOW_ITEM, FALSE,
  788.     X            PANEL_LABEL_STRING,
  789.     X            "Mark in month/year display:",
  790.     X            PANEL_CHOICE_STRINGS, "Yes", "No", 0,
  791.     X            PANEL_ITEM_X, ATTR_COL(1),
  792.     X            PANEL_ITEM_Y, ATTR_ROW(5),
  793.     X            0);
  794.     X
  795.     X    window_fit(attr_panel);
  796.     X    window_fit(attr_frame);
  797.     X}
  798.     X
  799.     X/*
  800.     X * create a popup to choose delete mode
  801.     X */
  802.     Xcreate_del_frame()
  803.     X{
  804.     X    /* create new frame and control panel */
  805.     X    del_frame = window_create(frame, FRAME, FRAME_NO_CONFIRM, TRUE,
  806.     X            FRAME_SHOW_LABEL, FALSE,
  807.     X            WIN_ERROR_MSG, "Can't create delete frame.",
  808.     X            0);
  809.     X
  810.     X    del_panel = window_create(del_frame, PANEL,
  811.     X            WIN_FONT, font,
  812.     X            0);
  813.     X    
  814.     X    (void) panel_create_item(del_panel, PANEL_BUTTON, PANEL_NOTIFY_PROC,
  815.     X            del_done, PANEL_LABEL_IMAGE,
  816.     X            panel_button_image(del_panel, "Accept", 6, font),
  817.     X            PANEL_SHOW_ITEM, TRUE,
  818.     X            PANEL_ITEM_X, ATTR_COL(30),
  819.     X            PANEL_ITEM_Y, ATTR_ROW(0),
  820.     X            0);
  821.     X
  822.     X    (void) panel_create_item(del_panel, PANEL_BUTTON, PANEL_NOTIFY_PROC,
  823.     X            attr_abort, PANEL_LABEL_IMAGE,
  824.     X            panel_button_image(del_panel, "Abort", 5, font),
  825.     X            PANEL_SHOW_ITEM, TRUE,
  826.     X            PANEL_ITEM_X, ATTR_COL(40),
  827.     X            PANEL_ITEM_Y, ATTR_ROW(0),
  828.     X            0);
  829.     X
  830.     X    (void) panel_create_item(del_panel, PANEL_MESSAGE,
  831.     X            PANEL_SHOW_ITEM, TRUE,
  832.     X            PANEL_LABEL_STRING, "This is a recurring appointment.",
  833.     X            PANEL_LABEL_X, ATTR_COL(1),
  834.     X            PANEL_LABEL_Y, ATTR_ROW(1)+5,
  835.     X            PANEL_LABEL_BOLD, TRUE,
  836.     X            0);
  837.     X
  838.     X    del_choice_pi = panel_create_item(del_panel, PANEL_CYCLE,
  839.     X            PANEL_SHOW_ITEM, TRUE,
  840.     X            PANEL_LABEL_STRING, "Do you wish to:",
  841.     X            PANEL_CHOICE_STRINGS, "Delete this occurrance only", "Delete all occurrances", 0,
  842.     X            PANEL_ITEM_X, ATTR_COL(1),
  843.     X            PANEL_ITEM_Y, ATTR_ROW(2)+5,
  844.     X            0);
  845.     X
  846.     X    window_fit(del_panel);
  847.     X    window_fit(del_frame);
  848.     X}
  849.     X
  850.     X#ifndef NO_SUN_MOON
  851.     X/*
  852.     X * create popup for sun data frame
  853.     X */
  854.     Xsun_data_frame()
  855.     X{
  856.     X    Panel spanel;
  857.     X
  858.     X    /* create new frame and canvas */
  859.     X    if (!sframe) {
  860.     X        sframe = window_create(frame, FRAME, FRAME_NO_CONFIRM, TRUE,
  861.     X                WIN_SHOW, TRUE, WIN_X, ATTR_COL(12),
  862.     X                FRAME_LABEL, "Solar Data",
  863.     X                FRAME_SHOW_LABEL, TRUE,
  864.     X                FRAME_DONE_PROC, sframe_done,
  865.     X                WIN_ERROR_MSG, "Can't create sun data frame.",
  866.     X                0);
  867.     X
  868.     X        spanel = window_create(sframe, PANEL, WIN_FONT, font,
  869.     X                WIN_WIDTH, 55*font->pf_defaultsize.x,
  870.     X                WIN_ERROR_MSG, "Can't create sun data panel.",
  871.     X                0);
  872.     X    
  873.     X        (void) panel_create_item(spanel, PANEL_BUTTON, PANEL_NOTIFY_PROC,
  874.     X                sdone_proc, PANEL_LABEL_IMAGE,
  875.     X                panel_button_image(spanel, "Done", 4, font),
  876.     X                PANEL_SHOW_ITEM, TRUE,
  877.     X                PANEL_ITEM_X, ATTR_COL(45),
  878.     X                PANEL_ITEM_Y, ATTR_ROW(0),
  879.     X                0);
  880.     X
  881.     X        sdate_pi = panel_create_item(spanel, PANEL_MESSAGE,
  882.     X                PANEL_ITEM_X, ATTR_COL(8),
  883.     X                PANEL_ITEM_Y, ATTR_ROW(0),
  884.     X                /* string filled in later */
  885.     X                PANEL_LABEL_STRING, "",
  886.     X                PANEL_LABEL_FONT, font,
  887.     X                0);
  888.     X    
  889.     X        window_fit_height(spanel);
  890.     X        scanvas = window_create(sframe, CANVAS, WIN_BELOW, spanel,
  891.     X                WIN_X, 0,
  892.     X                WIN_HEIGHT, 17*font->pf_defaultsize.y,
  893.     X                WIN_CONSUME_PICK_EVENT, WIN_NO_EVENTS,
  894.     X                WIN_CONSUME_KBD_EVENT, WIN_NO_EVENTS,
  895.     X                WIN_ERROR_MSG, "Can't create sun data canvas.",
  896.     X                0);
  897.     X    
  898.     X        write_sun_data();
  899.     X        window_fit(sframe);
  900.     X    } else
  901.     X        write_sun_data();
  902.     X}
  903.     X
  904.     X/*
  905.     X * create popup for moon data frame
  906.     X */
  907.     Xmoon_data_frame()
  908.     X{
  909.     X    Panel mpanel;
  910.     X
  911.     X    /* create new frame and canvas */
  912.     X    if (!mframe) {
  913.     X        mframe = window_create(frame, FRAME, FRAME_NO_CONFIRM, TRUE,
  914.     X                WIN_SHOW, TRUE, WIN_X, ATTR_COL(12),
  915.     X                FRAME_LABEL, "Lunar Data",
  916.     X                FRAME_SHOW_LABEL, TRUE,
  917.     X                FRAME_DONE_PROC, mframe_done,
  918.     X                WIN_ERROR_MSG, "Can't create moon data frame.",
  919.     X                0);
  920.     X
  921.     X        mpanel = window_create(mframe, PANEL, WIN_FONT, font,
  922.     X                WIN_WIDTH, 70*font->pf_defaultsize.x,
  923.     X                WIN_ERROR_MSG, "Can't create moon data panel.",
  924.     X                0);
  925.     X    
  926.     X        (void) panel_create_item(mpanel, PANEL_BUTTON, PANEL_NOTIFY_PROC,
  927.     X                mdone_proc, PANEL_LABEL_IMAGE,
  928.     X                panel_button_image(mpanel, "Done", 4, font),
  929.     X                PANEL_SHOW_ITEM, TRUE,
  930.     X                PANEL_ITEM_X, ATTR_COL(60),
  931.     X                PANEL_ITEM_Y, ATTR_ROW(0),
  932.     X                0);
  933.     X
  934.     X        mdate_pi = panel_create_item(mpanel, PANEL_MESSAGE,
  935.     X                PANEL_ITEM_X, ATTR_COL(8),
  936.     X                PANEL_ITEM_Y, ATTR_ROW(0),
  937.     X                /* string filled in later */
  938.     X                PANEL_LABEL_STRING, "",
  939.     X                PANEL_LABEL_FONT, font,
  940.     X                0);
  941.     X    
  942.     X        window_fit_height(mpanel);
  943.     X        mcanvas = window_create(mframe, CANVAS, WIN_BELOW, mpanel,
  944.     X                WIN_X, 0,
  945.     X                WIN_HEIGHT, 17*font->pf_defaultsize.y,
  946.     X                CANVAS_RETAINED, TRUE,
  947.     X                WIN_CONSUME_PICK_EVENT, WIN_NO_EVENTS,
  948.     X                WIN_CONSUME_KBD_EVENT, WIN_NO_EVENTS,
  949.     X                WIN_ERROR_MSG, "Can't create moon data canvas.",
  950.     X                0);
  951.     X    
  952.     X        write_moon_data();
  953.     X        window_fit(mframe);
  954.     X    } else
  955.     X        write_moon_data();
  956.     X}
  957.     X#endif    /* NO_SUN_MOON */
  958.     X
  959.     X/*
  960.     X * create a popup to allow selecting a different appointment file
  961.     X */
  962.     Xcreate_file_frame()
  963.     X{
  964.     X
  965.     X    /* create new frame and control panel */
  966.     X    fileframe = window_create(frame, FRAME, FRAME_NO_CONFIRM, TRUE,
  967.     X            FRAME_LABEL, "File Selection",
  968.     X            FRAME_SHOW_LABEL, TRUE,
  969.     X            FRAME_DONE_PROC, fileframe_done,
  970.     X            WIN_ERROR_MSG, "Can't create file frame.",
  971.     X            0);
  972.     X
  973.     X    filepanel = window_create(fileframe, PANEL, WIN_FONT, font,
  974.     X            PANEL_BLINK_CARET, TRUE,
  975.     X            0);
  976.     X    
  977.     X    file_ro_pi = panel_create_item(filepanel, PANEL_CYCLE, PANEL_CHOICE_STRINGS,
  978.     X            "Read Only", "Read/Write", 0,
  979.     X            PANEL_SHOW_ITEM, TRUE,
  980.     X            PANEL_ITEM_X, ATTR_COL(1),
  981.     X            PANEL_ITEM_Y, ATTR_ROW(0),
  982.     X            0);
  983.     X
  984.     X    (void) panel_create_item(filepanel, PANEL_BUTTON, PANEL_NOTIFY_PROC,
  985.     X            file_orig, PANEL_LABEL_IMAGE,
  986.     X            panel_button_image(filepanel, "Original", 7, font),
  987.     X            PANEL_SHOW_ITEM, TRUE,
  988.     X            PANEL_ITEM_X, ATTR_COL(17),
  989.     X            PANEL_ITEM_Y, ATTR_ROW(0),
  990.     X            0);
  991.     X
  992.     X    (void) panel_create_item(filepanel, PANEL_BUTTON, PANEL_NOTIFY_PROC,
  993.     X            file_accept, PANEL_LABEL_IMAGE,
  994.     X            panel_button_image(filepanel, "Accept", 6, font),
  995.     X            PANEL_SHOW_ITEM, TRUE,
  996.     X            PANEL_ITEM_X, ATTR_COL(27),
  997.     X            PANEL_ITEM_Y, ATTR_ROW(0),
  998.     X            0);
  999.     X
  1000.     X    (void) panel_create_item(filepanel, PANEL_BUTTON, PANEL_NOTIFY_PROC,
  1001.     X            file_reset, PANEL_LABEL_IMAGE,
  1002.     X            panel_button_image(filepanel, "Reset", 5, font),
  1003.     X            PANEL_SHOW_ITEM, TRUE,
  1004.     X            PANEL_ITEM_X, ATTR_COL(35),
  1005.     X            PANEL_ITEM_Y, ATTR_ROW(0),
  1006.     X            0);
  1007.     X
  1008.     X    (void) panel_create_item(filepanel, PANEL_BUTTON, PANEL_NOTIFY_PROC,
  1009.     X            file_save, PANEL_LABEL_IMAGE,
  1010.     X            panel_button_image(filepanel, "Update", 6, font),
  1011.     X            PANEL_SHOW_ITEM, TRUE,
  1012.     X            PANEL_ITEM_X, ATTR_COL(42),
  1013.     X            PANEL_ITEM_Y, ATTR_ROW(0),
  1014.     X            0);
  1015.     X
  1016.     X    (void) panel_create_item(filepanel, PANEL_BUTTON, PANEL_NOTIFY_PROC,
  1017.     X            file_done, PANEL_LABEL_IMAGE,
  1018.     X            panel_button_image(filepanel, "Done", 4, font),
  1019.     X            PANEL_SHOW_ITEM, TRUE,
  1020.     X            PANEL_ITEM_X, ATTR_COL(50),
  1021.     X            PANEL_ITEM_Y, ATTR_ROW(0),
  1022.     X            0);
  1023.     X
  1024.     X    (void) panel_create_item(filepanel, PANEL_MESSAGE,
  1025.     X            PANEL_SHOW_ITEM, TRUE,
  1026.     X            PANEL_LABEL_STRING, "Enter the desired appointment file",
  1027.     X            PANEL_LABEL_X, ATTR_COL(6),
  1028.     X            PANEL_LABEL_Y, ATTR_ROW(2),
  1029.     X            PANEL_LABEL_BOLD, TRUE,
  1030.     X            0);
  1031.     X
  1032.     X    filename_pi = panel_create_item(filepanel, PANEL_TEXT,
  1033.     X            PANEL_SHOW_ITEM, TRUE,
  1034.     X            PANEL_LABEL_STRING, "Filename:",
  1035.     X            PANEL_LABEL_BOLD, TRUE,
  1036.     X            PANEL_VALUE, 0, PANEL_VALUE_STORED_LENGTH, 128,
  1037.     X            PANEL_VALUE_DISPLAY_LENGTH, 30,
  1038.     X            PANEL_ITEM_X, ATTR_COL(1),
  1039.     X            PANEL_ITEM_Y, ATTR_ROW(3),
  1040.     X            PANEL_BLINK_CARET, TRUE,
  1041.     X            0);
  1042.     X
  1043.     X    window_fit(filepanel);
  1044.     X    window_fit(fileframe);
  1045.     X}
  1046.     X
  1047.     X/*
  1048.     X * create a popup to display an error message
  1049.     X */
  1050.     Xcreate_prompt_frame(str1, buttonflag)
  1051.     Xchar *str1;
  1052.     X{
  1053.     X    static Panel_item prompt_panel;
  1054.     X    static Panel_item msg_pi, yes_pi, no_pi = 0;
  1055.     X
  1056.     X    if (!prompt_frame) {
  1057.     X        /* create new frame and control panel */
  1058.     X        prompt_frame = window_create(frame, FRAME, FRAME_NO_CONFIRM, TRUE,
  1059.     X                FRAME_SHOW_LABEL, FALSE,
  1060.     X                WIN_SHOW, TRUE,
  1061.     X                WIN_X, ATTR_COL(15), WIN_Y, ATTR_ROW(15),
  1062.     X                WIN_ERROR_MSG, "Can't create error frame.",
  1063.     X                0);
  1064.     X
  1065.     X        prompt_panel = window_create(prompt_frame, PANEL,
  1066.     X                PANEL_ACCEPT_KEYSTROKE, FALSE,
  1067.     X                WIN_FONT, font,
  1068.     X                0);
  1069.     X    } else {
  1070.     X        /* existing frame, delete the items */
  1071.     X        panel_destroy_item(msg_pi);
  1072.     X        panel_destroy_item(yes_pi);
  1073.     X        if (no_pi) {
  1074.     X            panel_destroy_item(no_pi);
  1075.     X            no_pi = 0;
  1076.     X        }
  1077.     X    }
  1078.     X    
  1079.     X    /* create new message and button panel items */
  1080.     X    msg_pi = panel_create_item(prompt_panel, PANEL_MESSAGE,
  1081.     X            PANEL_SHOW_ITEM, TRUE,
  1082.     X            PANEL_ITEM_X, ATTR_COL(1),
  1083.     X            PANEL_ITEM_Y, ATTR_ROW(0),
  1084.     X            PANEL_LABEL_STRING, str1,
  1085.     X            PANEL_LABEL_BOLD, TRUE,
  1086.     X            0);
  1087.     X
  1088.     X    if (buttonflag) {
  1089.     X        yes_pi = panel_create_item(prompt_panel, PANEL_BUTTON,
  1090.     X                PANEL_SHOW_ITEM, TRUE,
  1091.     X                PANEL_ITEM_X, ATTR_COL(4),
  1092.     X                PANEL_ITEM_Y, ATTR_ROW(2),
  1093.     X                PANEL_NOTIFY_PROC, prompt_yes_notify,
  1094.     X                PANEL_LABEL_IMAGE,
  1095.     X                panel_button_image(prompt_panel, "Yes", 3, font),
  1096.     X                0);
  1097.     X
  1098.     X        no_pi = panel_create_item(prompt_panel, PANEL_MESSAGE,
  1099.     X                PANEL_SHOW_ITEM, TRUE,
  1100.     X                PANEL_ITEM_X, ATTR_COL(12),
  1101.     X                PANEL_ITEM_Y, ATTR_ROW(2),
  1102.     X                PANEL_NOTIFY_PROC, prompt_no_notify,
  1103.     X                PANEL_LABEL_IMAGE,
  1104.     X                panel_button_image(prompt_panel, "No", 2, font),
  1105.     X                0);
  1106.     X    } else {
  1107.     X        yes_pi = panel_create_item(prompt_panel, PANEL_MESSAGE,
  1108.     X                PANEL_SHOW_ITEM, TRUE,
  1109.     X                PANEL_ITEM_X, ATTR_COL(12),
  1110.     X                PANEL_ITEM_Y, ATTR_ROW(2),
  1111.     X                PANEL_NOTIFY_PROC, prompt_yes_notify,
  1112.     X                PANEL_LABEL_IMAGE,
  1113.     X                panel_button_image(prompt_panel, "Ok", 2, font),
  1114.     X                0);
  1115.     X    }
  1116.     X
  1117.     X    window_fit(prompt_panel);
  1118.     X    window_fit(prompt_frame);
  1119.     X}
  1120.     X
  1121.     X#ifndef NO_PRINTER
  1122.     X/* create popup to change the printer */
  1123.     Xcreate_print_frame()
  1124.     X{
  1125.     X    Panel prpanel;
  1126.     X
  1127.     X    prframe = window_create(frame, FRAME, FRAME_NO_CONFIRM, TRUE,
  1128.     X            WIN_SHOW, FALSE, WIN_X, ATTR_COL(12),
  1129.     X            FRAME_LABEL, "Change Printer",
  1130.     X            FRAME_SHOW_LABEL, TRUE,
  1131.     X            FRAME_DONE_PROC, prframe_done,
  1132.     X            WIN_ERROR_MSG, "Can't create printer frame.",
  1133.     X            0);
  1134.     X
  1135.     X    prpanel = window_create(prframe, PANEL, WIN_FONT, font,
  1136.     X            WIN_ERROR_MSG, "Can't create printer panel.",
  1137.     X            0);
  1138.     X    
  1139.     X    (void) panel_create_item(prpanel, PANEL_BUTTON, PANEL_NOTIFY_PROC,
  1140.     X            prdone_proc, PANEL_LABEL_IMAGE,
  1141.     X            panel_button_image(prpanel, "Done", 4, font),
  1142.     X            PANEL_SHOW_ITEM, TRUE,
  1143.     X            PANEL_ITEM_X, ATTR_COL(34),
  1144.     X            PANEL_ITEM_Y, ATTR_ROW(0),
  1145.     X            0);
  1146.     X
  1147.     X    prcmd_pi = panel_create_item(prpanel, PANEL_TEXT,
  1148.     X            PANEL_SHOW_ITEM, TRUE,
  1149.     X            PANEL_ITEM_X, ATTR_COL(1),
  1150.     X            PANEL_ITEM_Y, ATTR_ROW(1)+5,
  1151.     X            PANEL_LABEL_STRING, "Print command:",
  1152.     X            PANEL_LABEL_FONT, font,
  1153.     X            PANEL_LABEL_BOLD, TRUE,
  1154.     X            PANEL_VALUE_STORED_LENGTH, 128,
  1155.     X            PANEL_VALUE_DISPLAY_LENGTH, 30,
  1156.     X            PANEL_BLINK_CARET, TRUE,
  1157.     X            0);
  1158.     X    
  1159.     X    panel_set_value(prcmd_pi, printer);
  1160.     X    window_fit(prpanel);
  1161.     X    window_fit(prframe);
  1162.     X}
  1163.     X#endif    /* NO_PRINTER */
  1164.     X
  1165.     X/* create popup to change the date */
  1166.     Xcreate_date_frame()
  1167.     X{
  1168.     X    Panel dtpanel;
  1169.     X    char date[9];
  1170.     X
  1171.     X    date_frame = window_create(frame, FRAME, FRAME_NO_CONFIRM, TRUE,
  1172.     X            WIN_SHOW, FALSE, WIN_X, ATTR_COL(12),
  1173.     X            FRAME_LABEL, "Change Current Date",
  1174.     X            FRAME_SHOW_LABEL, TRUE,
  1175.     X            FRAME_DONE_PROC, dtframe_done,
  1176.     X            WIN_ERROR_MSG, "Can't create date frame.",
  1177.     X            0);
  1178.     X
  1179.     X    dtpanel = window_create(date_frame, PANEL, WIN_FONT, font,
  1180.     X            WIN_ERROR_MSG, "Can't create date panel.",
  1181.     X            0);
  1182.     X    
  1183.     X    (void) panel_create_item(dtpanel, PANEL_BUTTON, PANEL_NOTIFY_PROC,
  1184.     X            dtdone_proc, PANEL_LABEL_IMAGE,
  1185.     X            panel_button_image(dtpanel, "Done", 4, font),
  1186.     X            PANEL_SHOW_ITEM, TRUE,
  1187.     X            PANEL_ITEM_X, ATTR_COL(34),
  1188.     X            PANEL_ITEM_Y, ATTR_ROW(0),
  1189.     X            0);
  1190.     X
  1191.     X    setdate_pi = panel_create_item(dtpanel, PANEL_TEXT,
  1192.     X            PANEL_SHOW_ITEM, TRUE,
  1193.     X            PANEL_ITEM_X, ATTR_COL(1),
  1194.     X            PANEL_ITEM_Y, ATTR_ROW(1)+5,
  1195.     X            PANEL_LABEL_STRING, "Enter date (D, M/D, or M/D/Y):",
  1196.     X            PANEL_LABEL_FONT, font,
  1197.     X            PANEL_LABEL_BOLD, TRUE,
  1198.     X            PANEL_VALUE_STORED_LENGTH, 10,
  1199.     X            PANEL_VALUE_DISPLAY_LENGTH, 10,
  1200.     X            PANEL_BLINK_CARET, TRUE,
  1201.     X            0);
  1202.     X    
  1203.     X    sprintf(date, "%d/%d/%02d", current.tm_mon+1, current.tm_mday, current.tm_year);
  1204.     X    panel_set_value(setdate_pi, date);
  1205.     X    window_fit(dtpanel);
  1206.     X    window_fit(date_frame);
  1207.     X}
  1208.     X
  1209.     X/* replace cursors with hourglass symbol to show we're waiting */
  1210.     Xlock_cursors()
  1211.     X{
  1212.     X    panel_cursor = cursor_copy((Cursor) window_get(panel, WIN_CURSOR));
  1213.     X    canvas_cursor = cursor_copy((Cursor) window_get(canvas, WIN_CURSOR));
  1214.     X    window_set(panel, WIN_CURSOR, wait_cursor, 0);
  1215.     X    window_set(canvas, WIN_CURSOR, wait_cursor, 0);
  1216.     X}
  1217.     X
  1218.     X/* restore cursors */
  1219.     Xunlock_cursors()
  1220.     X{
  1221.     X    window_set(panel, WIN_CURSOR, panel_cursor, 0);
  1222.     X    window_set(canvas, WIN_CURSOR, canvas_cursor, 0);
  1223.     X    cursor_destroy(panel_cursor);
  1224.     X    cursor_destroy(canvas_cursor);
  1225.     X}
  1226. SHAR_EOF
  1227. if test 30604 -ne "`wc -c < 'tool.c'`"
  1228. then
  1229.     echo shar: error transmitting "'tool.c'" '(should have been 30604 characters)'
  1230. fi
  1231. fi # end of overwriting check
  1232. echo shar: extracting "'utils.c'" '(31671 characters)'
  1233. if test -f 'utils.c'
  1234. then
  1235.     echo shar: will not over-write existing file "'utils.c'"
  1236. else
  1237. sed 's/^    X//' << \SHAR_EOF > 'utils.c'
  1238.     X/*
  1239.     X * $Header: utils.c,v 2.2 89/05/16 16:30:18 billr Exp $
  1240.     X */
  1241.     X/*
  1242.     X * utils.c
  1243.     X *
  1244.     X * calentool - a year/month/week/day-at-a-glance calendar for Sun workstations.
  1245.     X *
  1246.     X * Author: Philip Heller, Sun Microsystems. Inc. <terrapin!heller@sun.com>
  1247.     X *
  1248.     X * Original source Copyright (C) 1987, Sun Microsystems, Inc.
  1249.     X *    All Rights Reserved
  1250.     X * Permission is hereby granted to use and modify this program in source
  1251.     X * or binary form as long as it is not sold for profit and this copyright
  1252.     X * notice remains intact.
  1253.     X *
  1254.     X *
  1255.     X * Changes/additions by: Bill Randle, Tektronix, Inc. <billr@saab.CNA.TEK.COM>
  1256.     X *
  1257.     X * Changes and additions Copyright (C) 1988, 1989 Tektronix, Inc.
  1258.     X *    All Rights Reserved
  1259.     X * Permission is hereby granted to use and modify the modifications in source
  1260.     X * or binary form as long as they are not sold for profit and this copyright
  1261.     X * notice remains intact.
  1262.     X */
  1263.     X/********************************************
  1264.     X *                        *
  1265.     X *              Utility routines.        *
  1266.     X *                        *
  1267.     X ********************************************/
  1268.     X
  1269.     X
  1270.     X
  1271.     X#include "ct.h"
  1272.     X#include <stdio.h>
  1273.     X#include <suntool/sunview.h>
  1274.     X#include <suntool/canvas.h>
  1275.     X#include <ctype.h>
  1276.     X#include <sys/types.h>
  1277.     X#include <sys/file.h>
  1278.     X#include <sys/stat.h>
  1279.     X#include <sys/errno.h>
  1280.     X
  1281.     X
  1282.     Xextern struct tm today, current;
  1283.     Xextern struct tm First;
  1284.     Xextern int day_is_open, read_only;
  1285.     Xextern struct dayslot slots[];
  1286.     Xextern char apts_pathname[], tmpapts_pathname[];
  1287.     Xextern int dayslot_width, nr_weekdays, n_tslots;
  1288.     Xextern int dayslot_height;
  1289.     Xextern char *monthnames[], *daynames[];
  1290.     Xextern char *mailto, *progname;
  1291.     Xextern int one_based, version2, new_entry;
  1292.     Xextern int findex;
  1293.     Xextern struct appt_entry future[];
  1294.     Xextern char todays_date[];
  1295.     Xextern char apts_dir[], lib_dir[];
  1296.     Xextern char printer[];
  1297.     Xextern int include_old, save_old;
  1298.     Xextern Frame frame;
  1299.     Xextern Canvas canvas;
  1300.     Xextern Pixwin *main_pixwin;
  1301.     Xextern int mainsw_state;
  1302.     Xextern Pixfont *font, *sfont;
  1303.     Xextern Frame prompt_frame;
  1304.     Xextern int update_interval;
  1305.     Xextern int errno;
  1306.     X
  1307.     Xchar inbuf[512], strbuf[256], errbuf[64];
  1308.     Xchar todays_date[32];
  1309.     Xstatic int including;
  1310.     Xstatic int log_to_console;
  1311.     Xchar *daynames[] = {"Sunday","Monday","Tuesday","Wednesday",
  1312.     X               "Thursday","Friday","Saturday"};
  1313.     Xchar *monthnames[] = {"January","February","March","April",
  1314.     X                 "May","June","July","August",
  1315.     X                 "September","October","November","December"};
  1316.     Xchar *dayname[7] = {"SU", "MO", "TU", "WE", "TH", "FR", "SA"};
  1317.     Xchar rasfile[] = "/usr/tmp/calentool.ras";
  1318.     Xchar psfile[] = "/usr/tmp/calentool.ps";
  1319.     Xchar *fname = 0;
  1320.     X
  1321.     Xextern char *strcpy(), *strcat();
  1322.     X
  1323.     X/*
  1324.     X * sets "today" and current time
  1325.     X */
  1326.     Xvoid
  1327.     Xget_today()
  1328.     X{
  1329.     X    struct tm *tm;
  1330.     X    struct timeval tv;
  1331.     X
  1332.     X    gettimeofday(&tv, 0);
  1333.     X    tm = localtime(&tv.tv_sec);
  1334.     X
  1335.     X    today = *tm;
  1336.     X
  1337.     X    strcpy(todays_date, asctime(tm));
  1338.     X    if (update_interval >= 60)
  1339.     X        /* overwrite seconds field with year */
  1340.     X        sprintf(&todays_date[16], " %d", today.tm_year+1900);
  1341.     X    else
  1342.     X        /* just delete trailing \n */
  1343.     X        todays_date[strlen(todays_date)-1] = '\0';
  1344.     X}
  1345.     X
  1346.     X/*
  1347.     X *    Reset some values in current tm structure. Year, month and
  1348.     X *    day-of-month are valid but day and/or month may be < 0 or
  1349.     X *    greater than the maximum value, in which case they are adjusted
  1350.     X *    accordingly. Day-of-year and day-of-week are then recalculated.
  1351.     X */
  1352.     Xvoid
  1353.     Xfix_current_day()
  1354.     X{
  1355.     X    int month, totdays = 0;
  1356.     X    struct tm from, to;
  1357.     X
  1358.     X    if (current.tm_mon < JAN) {
  1359.     X        current.tm_mon = DEC;
  1360.     X        current.tm_year--;
  1361.     X    } else if (current.tm_mon > DEC) {
  1362.     X        current.tm_mon = JAN;
  1363.     X        current.tm_year++;
  1364.     X    }
  1365.     X    if (current.tm_mday < 1) {
  1366.     X        current.tm_mon--;
  1367.     X        if (current.tm_mon < JAN) {
  1368.     X            current.tm_mon = DEC;
  1369.     X            current.tm_year--;
  1370.     X        }
  1371.     X        current.tm_mday += monthlength(current.tm_mon);
  1372.     X    } else if (current.tm_mday > monthlength(current.tm_mon)) {
  1373.     X        current.tm_mday -= monthlength(current.tm_mon);
  1374.     X        current.tm_mon++;
  1375.     X        if (current.tm_mon > DEC) {
  1376.     X            current.tm_mon = JAN;
  1377.     X            current.tm_year++;
  1378.     X        }
  1379.     X    }
  1380.     X    current.tm_yday = current.tm_mday - 1;
  1381.     X    for (month = 0; month < current.tm_mon; month++) {
  1382.     X        current.tm_yday += monthlength(month);
  1383.     X    }
  1384.     X    if ((current.tm_year < today.tm_year)
  1385.     X        || ((current.tm_year == today.tm_year)
  1386.     X        && (current.tm_yday < today.tm_yday))) {
  1387.     X        from = current;
  1388.     X        to = today;
  1389.     X    } else {
  1390.     X        from = today;
  1391.     X        to = current;
  1392.     X    }
  1393.     X    if (from.tm_year != to.tm_year) {
  1394.     X        for (totdays = 0; from.tm_year < to.tm_year; from.tm_year++)
  1395.     X            totdays += dysize(from.tm_year + 1900);
  1396.     X    }
  1397.     X    totdays += to.tm_yday - from.tm_yday;
  1398.     X    if ((current.tm_year < today.tm_year)
  1399.     X        || ((current.tm_year == today.tm_year)
  1400.     X        && (current.tm_yday < today.tm_yday)))
  1401.     X        totdays = -totdays;
  1402.     X    current.tm_wday =
  1403.     X        ((totdays % 7) + 7 + today.tm_wday) % 7;
  1404.     X}
  1405.     X
  1406.     X/*
  1407.     X * Compares two sets of year/month/day.  Returns -1 if the first is earlier than
  1408.     X * the second, +1 if later, 0 if they are the same.
  1409.     X */
  1410.     Xymd_compare(day0, day1)
  1411.     Xstruct tm day0, day1;
  1412.     X{
  1413.     X        if (day0.tm_year > day1.tm_year) return(1);
  1414.     X        if (day0.tm_year < day1.tm_year) return(-1);
  1415.     X        if (day0.tm_mon > day1.tm_mon) return(1);
  1416.     X        if (day0.tm_mon < day1.tm_mon) return(-1);
  1417.     X        if (day0.tm_mday > day1.tm_mday) return(1);
  1418.     X        if (day0.tm_mday < day1.tm_mday) return(-1);
  1419.     X        return(0);
  1420.     X}
  1421.     X
  1422.     Xint
  1423.     Xmonthlength(month)
  1424.     Xint    month;
  1425.     X{
  1426.     X    static int    monthlengths[] = {31,28,31,30,31,30,31,31,30,31,30,31};
  1427.     X
  1428.     X    if (month == FEB && (dysize(current.tm_year + 1900) == 366))
  1429.     X        return(29);
  1430.     X    else
  1431.     X        return(monthlengths[month]);
  1432.     X}
  1433.     X
  1434.     X/*
  1435.     X *
  1436.     X * Append data from active timeslots to end of "tmp.appointments"
  1437.     X * file, then copy "tmp.appointments" to "appointments".  Note that
  1438.     X * when we opened the current day we filtered "appointments":
  1439.     X * all items that applied to the current day were displayed and
  1440.     X * stored in slots; all others were copied to "tmp.appointments".
  1441.     X * So by now "tmp.appointments" contains no entries for the
  1442.     X * current day.
  1443.     X * As an optimization, if nothing changed in the day then the
  1444.     X * original appointments file is left unchanged.
  1445.     X *
  1446.     X */
  1447.     X
  1448.     Xclose_day()
  1449.     X{
  1450.     X        int i, j;
  1451.     X        FILE *f;
  1452.     X    struct stat sbuf;
  1453.     X    struct appt_entry *aptr, *optr;
  1454.     X
  1455.     X    if (read_only || !new_entry) {
  1456.     X        new_entry = 0;
  1457.     X        day_is_open = FALSE;
  1458.     X        return(0);
  1459.     X    }
  1460.     X
  1461.     X    f = fopen(tmpapts_pathname, "a+");
  1462.     X    if (f == NULL) {
  1463.     X        err_rpt("can't open temp file for appending", NON_FATAL);
  1464.     X        day_is_open = FALSE;
  1465.     X        return(1);
  1466.     X    }
  1467.     X    
  1468.     X    for (i=0; i<N_SLOTS; i++) {
  1469.     X                if (slots[i].first != NULL) {
  1470.     X            aptr = slots[i].first;
  1471.     X            if (put_aentry(f, aptr))
  1472.     X                /* write error */
  1473.     X                break;
  1474.     X            optr = aptr;
  1475.     X            while (aptr = aptr->next) {
  1476.     X                free(optr);
  1477.     X                if (put_aentry(f, aptr))
  1478.     X                    /* write error */
  1479.     X                    break;
  1480.     X                optr = aptr;
  1481.     X            }
  1482.     X            free(optr);
  1483.     X        }
  1484.     X        }
  1485.     X    if (ferror(f))
  1486.     X        err_rpt("write on temp file failed", FATAL);
  1487.     X        fclose(f);
  1488.     X    new_entry = 0;
  1489.     X    day_is_open = FALSE;
  1490.     X    /* don't rename zero length files */
  1491.     X    stat(tmpapts_pathname, &sbuf);
  1492.     X    if (sbuf.st_size == (off_t) 0)
  1493.     X        return(1);
  1494.     X    xrename(tmpapts_pathname, apts_pathname);
  1495.     X}
  1496.     X
  1497.     X/*
  1498.     X * get entry from appointments file
  1499.     X */
  1500.     Xget_aentry(apts_file, appt)
  1501.     XFILE *apts_file;
  1502.     Xstruct appt_entry *appt;
  1503.     X{
  1504.     X    char *ptr, *str;
  1505.     X    char *fgets(), *index();
  1506.     X    char *incl_ptr, incl_buf[128], wday[3];
  1507.     X    int i, lib;
  1508.     X    struct stat sbuf;
  1509.     X    static FILE *include;
  1510.     X
  1511.     X    appt->flags = appt->repeat = appt->lookahead = 0;
  1512.     X    appt->sindex = 0;
  1513.     X    appt->next = NULL;
  1514.     X    if (including) {
  1515.     X        if (fgets(inbuf, 512, include) == NULL) {
  1516.     X            /* end of include file - get next entry
  1517.     X             * from main file
  1518.     X             */
  1519.     X            including = 0;
  1520.     X            fclose(include);
  1521.     X            if (fgets(inbuf, 512, apts_file) == NULL)
  1522.     X                return(EOF);
  1523.     X        } else {
  1524.     X            including = 2;
  1525.     X            /* don't modify stuff from include files */
  1526.     X            appt->flags |= READONLY;
  1527.     X        }
  1528.     X    } else
  1529.     X        if (fgets(inbuf, 512, apts_file) == NULL)
  1530.     X            return(EOF);
  1531.     X    ptr = inbuf;
  1532.     X    if (*ptr == '#') {
  1533.     X        if (!strcmp(inbuf, HEADER) && !including) {
  1534.     X            /* first line in file read */
  1535.     X            if (include_old && (First.tm_year < today.tm_year)) {
  1536.     X                /* read in old include file (if it exists) */
  1537.     X                /* prepend directory info */
  1538.     X                sprintf(incl_buf, "%s/.appointments.%02d",
  1539.     X                    apts_dir, First.tm_year);
  1540.     X                if (!stat(incl_buf, &sbuf)) {
  1541.     X                    if ((include = fopen(incl_buf, "r")) == NULL)
  1542.     X                        err_rpt("can't open include file (ignored)", NON_FATAL);
  1543.     X                    else
  1544.     X                        including = 1;
  1545.     X                }
  1546.     X            }
  1547.     X        } else if (!strncmp(inbuf, "#include", 8)) {
  1548.     X            /* include file */
  1549.     X            if (including)
  1550.     X                err_rpt("include files may not be nested", FATAL);
  1551.     X            incl_ptr = strbuf;
  1552.     X            if ((ptr = index(inbuf, '"')) == NULL)
  1553.     X
  1554.     X                if ((ptr = index(inbuf, '<')) == NULL) {
  1555.     X                    err_rpt("missing '\"' or '<' in include file spec", NON_FATAL);
  1556.     X                    return(0);
  1557.     X                } else {
  1558.     X                    lib = 1;
  1559.     X                }
  1560.     X            else
  1561.     X                lib = 0;
  1562.     X            ptr++;
  1563.     X            while (*ptr && *ptr != '"' && *ptr != '>')
  1564.     X                *incl_ptr++ = *ptr++;
  1565.     X            if (! *ptr) {
  1566.     X                err_rpt("missing '\"' or '>' in include file spec", NON_FATAL);
  1567.     X                return(0);
  1568.     X            }
  1569.     X            *incl_ptr = '\0';
  1570.     X            if (strbuf[0] == '/')
  1571.     X                /* full pathname provided */
  1572.     X                strcpy(incl_buf, strbuf);
  1573.     X            else
  1574.     X                /* prepend directory info */
  1575.     X                if (lib)
  1576.     X                    sprintf(incl_buf, "%s/%s", lib_dir, strbuf);
  1577.     X                else
  1578.     X                    sprintf(incl_buf, "%s/%s", apts_dir, strbuf);
  1579.     X            if ((include = fopen(incl_buf, "r")) == NULL)
  1580.     X                err_rpt("can't open include file (ignored)", NON_FATAL);
  1581.     X            else 
  1582.     X                including = 1;
  1583.     X        }
  1584.     X        appt->flags |= A_COMMENT;
  1585.     X        return(0);
  1586.     X    }
  1587.     X    while (isspace(*ptr))
  1588.     X        ++ptr;
  1589.     X    if (!*ptr) {
  1590.     X        /* empty line */
  1591.     X        appt->flags |= A_COMMENT;
  1592.     X        return(0);
  1593.     X    }
  1594.     X    if (*ptr == '*') {
  1595.     X        appt->flags |= ALL_YEARS;
  1596.     X        appt->year = START_YEAR;
  1597.     X        ++ptr;    /* point to second '*' */
  1598.     X        ++ptr;    /* point to space */
  1599.     X    } else {
  1600.     X        appt->year = 0;
  1601.     X        while (isdigit(*ptr)) {
  1602.     X            appt->year *= 10;
  1603.     X            appt->year += *ptr++ - '0';
  1604.     X        }
  1605.     X        /* sanity check */
  1606.     X        if (appt->year < 0) {
  1607.     X            err_rpt("illegal year value (ignored)", NON_FATAL);
  1608.     X            return(1);
  1609.     X        }
  1610.     X    }
  1611.     X    while (isspace(*ptr))
  1612.     X        ++ptr;
  1613.     X    if (*ptr == '*') {
  1614.     X        appt->flags |= ALL_MONTHS;
  1615.     X        appt->month = 0;
  1616.     X        ++ptr;
  1617.     X    } else {
  1618.     X        appt->month = (*ptr - '0') * 10;
  1619.     X        appt->month += *++ptr - '0';
  1620.     X        if (one_based) (appt->month)--;
  1621.     X        /* sanity check */
  1622.     X        if (appt->month < JAN || appt->month > DEC) {
  1623.     X            /*
  1624.     X            sprintf(errbuf, "illegal month value [%d] (ignored)", appt->month);
  1625.     X            err_rpt(errbuf, NON_FATAL);
  1626.     X            */
  1627.     X            err_rpt("illegal month value (ignored)", NON_FATAL);
  1628.     X            return(1);
  1629.     X        }
  1630.     X    }
  1631.     X    ++ptr;
  1632.     X    while (isspace(*ptr))
  1633.     X        ++ptr;
  1634.     X    if (*ptr == '*') {
  1635.     X        appt->flags |= ALL_DAYS;
  1636.     X        appt->day = 0;
  1637.     X        appt->repeat = 1;
  1638.     X        ++ptr;
  1639.     X    } else if (isdigit(*ptr)) {
  1640.     X        appt->day = (*ptr - '0') * 10;
  1641.     X        appt->day += *++ptr - '0';
  1642.     X        if (!one_based) (appt->day)++;
  1643.     X        /* sanity check */
  1644.     X        if (appt->day < 1 || appt->day > 31) {
  1645.     X            err_rpt("illegal day value (ignored)", NON_FATAL);
  1646.     X            return(1);
  1647.     X        }
  1648.     X    } else {
  1649.     X        /* check for day names */
  1650.     X        wday[0] = islower(*ptr) ? toupper(*ptr) : *ptr;
  1651.     X        ++ptr;
  1652.     X        wday[1] = islower(*ptr) ? toupper(*ptr) : *ptr;
  1653.     X        wday[2] = '\0';
  1654.     X        i = 0;
  1655.     X        if (!strcmp(wday, dayname[i++]))
  1656.     X            appt->flags |= EVERY_SUN;
  1657.     X        else if (!strcmp(wday, dayname[i++]))
  1658.     X            appt->flags |= EVERY_MON;
  1659.     X        else if (!strcmp(wday, dayname[i++]))
  1660.     X            appt->flags |= EVERY_TUE;
  1661.     X        else if (!strcmp(wday, dayname[i++]))
  1662.     X            appt->flags |= EVERY_WED;
  1663.     X        else if (!strcmp(wday, dayname[i++]))
  1664.     X            appt->flags |= EVERY_THU;
  1665.     X        else if (!strcmp(wday, dayname[i++]))
  1666.     X            appt->flags |= EVERY_FRI;
  1667.     X        else if (!strcmp(wday, dayname[i]))
  1668.     X            appt->flags |= EVERY_SAT;
  1669.     X        else {
  1670.     X            /* sanity check */
  1671.     X            err_rpt("illegal day name (ignored)", NON_FATAL);
  1672.     X            return(1);
  1673.     X        }
  1674.     X        appt->day = 0;
  1675.     X        appt->flags |= REPEAT;
  1676.     X        appt->repeat = ALL_WEEKS;    /* default to every week */
  1677.     X    }
  1678.     X    ++ptr;
  1679.     X    while (isspace(*ptr))
  1680.     X        ++ptr;
  1681.     X    appt->hour = (*ptr - '0') * 10;
  1682.     X    appt->hour += *++ptr - '0';
  1683.     X    /* sanity check */
  1684.     X    if (appt->hour < 0 || (appt->hour > 23 && appt->hour != 99)) {
  1685.     X        err_rpt("illegal hour value (ignored)", NON_FATAL);
  1686.     X        return(1);
  1687.     X    }
  1688.     X    if ((version2 && appt->hour == 99) || (!version2 && appt->hour == 0))
  1689.     X        appt->flags |= A_NOTE;
  1690.     X    ++ptr;
  1691.     X    while (isspace(*ptr))
  1692.     X        ++ptr;
  1693.     X    appt->minute = (*ptr - '0') * 10;
  1694.     X    appt->minute += *++ptr - '0';
  1695.     X    /* sanity check */
  1696.     X    if (appt->minute < 0 || (appt->minute > 59 && appt->minute != 99)) {
  1697.     X        /* minutes currently can only be 00 or 30
  1698.     X         * unless it's a note.
  1699.     X         */
  1700.     X        err_rpt("illegal minute value (ignored)", NON_FATAL);
  1701.     X        return(1);
  1702.     X    }
  1703.     X    if ((appt->flags & A_NOTE) && version2 && appt->minute == 99)
  1704.     X        appt->flags |= MARKED;  /* don't show in mon/yr display */
  1705.     X    ++ptr;
  1706.     X    while (isspace(*ptr))
  1707.     X        ++ptr;
  1708.     X    appt->arrows = (*ptr - '0') * 10;
  1709.     X    appt->arrows += *++ptr - '0';
  1710.     X    /* sanity check */
  1711.     X    if (appt->arrows < 0 || appt->arrows > N_TSLOTS) {
  1712.     X        err_rpt("illegal arrow value (ignored)", NON_FATAL);
  1713.     X        return(1);
  1714.     X    }
  1715.     X    ++ptr;
  1716.     X    while (isspace(*ptr))
  1717.     X        ++ptr;
  1718.     X    /* lookahead and repeat entries are free format, i.e. they */
  1719.     X    /* can occur in either order */
  1720.     X    if (*ptr == '[') {
  1721.     X        appt->flags |= REPEAT;
  1722.     X        if (appt->flags & EVERY_SOMEDAY) {
  1723.     X            if ((appt->repeat = do_wk_repeat(&ptr)) < 0)
  1724.     X                return(1);
  1725.     X        } else {
  1726.     X            if ((appt->repeat = do_repeat(&ptr)) < 0)
  1727.     X                return(1);
  1728.     X        }
  1729.     X        if (*ptr == '<') {
  1730.     X            appt->flags |= LOOKAHEAD;
  1731.     X            if ((appt->lookahead = do_lookahead(&ptr)) < 0)
  1732.     X                return(1);
  1733.     X        }
  1734.     X        if (*ptr == '#') {
  1735.     X            appt->flags |= DELETED;
  1736.     X            ++ptr;
  1737.     X            while (isspace(*ptr))
  1738.     X                ++ptr;
  1739.     X        }
  1740.     X    } else if (*ptr == '<') {
  1741.     X        appt->flags |= LOOKAHEAD;
  1742.     X        if ((appt->lookahead = do_lookahead(&ptr)) < 0)
  1743.     X            return(1);
  1744.     X        if (*ptr == '[') {
  1745.     X            appt->flags |= REPEAT;
  1746.     X            if (appt->flags & EVERY_SOMEDAY) {
  1747.     X                if ((appt->repeat = do_wk_repeat(&ptr)) < 0)
  1748.     X                    return(1);
  1749.     X            } else {
  1750.     X                if ((appt->repeat = do_repeat(&ptr)) < 0)
  1751.     X                    return(1);
  1752.     X            }
  1753.     X        }
  1754.     X        if (*ptr == '#') {
  1755.     X            appt->flags |= DELETED;
  1756.     X            ++ptr;
  1757.     X            while (isspace(*ptr))
  1758.     X                ++ptr;
  1759.     X        }
  1760.     X    } else if (*ptr == '#') {
  1761.     X        appt->flags |= DELETED;
  1762.     X        ++ptr;
  1763.     X        while (isspace(*ptr))
  1764.     X            ++ptr;
  1765.     X    }
  1766.     X    str = strbuf;
  1767.     X    while (*ptr && *ptr != '\n')
  1768.     X        *str++ = *ptr++;
  1769.     X    *str = '\0';
  1770.     X    strcpy(appt->str, strbuf);
  1771.     X
  1772.     X    return(0);
  1773.     X}
  1774.     X
  1775.     X/* parse normal repeated entry field */
  1776.     Xdo_repeat(ptr)
  1777.     Xchar **ptr;
  1778.     X{
  1779.     X    int repeat = 0;
  1780.     X
  1781.     X    while (isdigit(*++*ptr))
  1782.     X        repeat = repeat * 10 + (int)(**ptr - '0');
  1783.     X    if (**ptr != ']') {
  1784.     X        err_rpt("bad entry (ignored)", NON_FATAL);
  1785.     X        return(-1);
  1786.     X    }
  1787.     X    /* sanity check */
  1788.     X    if (repeat < 0) {
  1789.     X        err_rpt("illegal repeat interval (ignored)", NON_FATAL);
  1790.     X        return(-1);
  1791.     X    }
  1792.     X    ++*ptr;
  1793.     X    while (isspace(**ptr))
  1794.     X        ++*ptr;
  1795.     X    return(repeat);
  1796.     X}
  1797.     X
  1798.     X/* parse weekly repeated entry field */
  1799.     Xdo_wk_repeat(ptr)
  1800.     Xchar **ptr;
  1801.     X{
  1802.     X    int repeat = 0;
  1803.     X
  1804.     X    while (*++*ptr != ']') {
  1805.     X        if (**ptr == ',')
  1806.     X            continue;    /* get next week */
  1807.     X        if (isdigit(**ptr)) {
  1808.     X            repeat |= 0x1<<(**ptr - '1');
  1809.     X        } else if (**ptr == 'L' || **ptr == 'l') {
  1810.     X            /* last week in month */
  1811.     X            repeat |= LAST_WEEK;
  1812.     X        } else {
  1813.     X            /* format error */
  1814.     X            err_rpt("illegal repeat specification (ignored)", NON_FATAL);
  1815.     X            return(-1);
  1816.     X        }
  1817.     X    }
  1818.     X    /* sanity check */
  1819.     X    if ((unsigned int)repeat > WEEK_LIMIT) {
  1820.     X        err_rpt("illegal weekly repeat (ignored)", NON_FATAL);
  1821.     X        return(-1);
  1822.     X    }
  1823.     X    ++*ptr;
  1824.     X    while (isspace(**ptr))
  1825.     X        ++*ptr;
  1826.     X
  1827.     X    return(repeat);
  1828.     X}
  1829.     X
  1830.     X/* parse lookahead entry field */
  1831.     Xdo_lookahead(ptr)
  1832.     Xchar **ptr;
  1833.     X{
  1834.     X    int lookahead = 0;
  1835.     X
  1836.     X    while (isdigit(*++*ptr))
  1837.     X        lookahead = lookahead * 10 + (int)(**ptr - '0');
  1838.     X    if (**ptr != '>') {
  1839.     X        err_rpt("bad entry (ignored)", NON_FATAL);
  1840.     X        return(-1);
  1841.     X    }
  1842.     X    /* sanity check */
  1843.     X    if (lookahead < 0) {
  1844.     X        err_rpt("illegal lookahead interval (ignored)", NON_FATAL);
  1845.     X        return(-1);
  1846.     X    }
  1847.     X    ++*ptr;
  1848.     X    while (isspace(**ptr))
  1849.     X        ++*ptr;
  1850.     X    return(lookahead);
  1851.     X}
  1852.     X
  1853.     X/*
  1854.     X * put entry into appointments file
  1855.     X */
  1856.     Xput_aentry(apts_file, appt)
  1857.     XFILE *apts_file;
  1858.     Xstruct appt_entry *appt;
  1859.     X{
  1860.     X    char *to_str();
  1861.     X
  1862.     X    if (read_only)
  1863.     X        return(0);
  1864.     X
  1865.     X    if (appt->flags & READONLY)
  1866.     X        /* don't copy include file entries */
  1867.     X        /* (the include directive is copied as a comment) */
  1868.     X        return(0);
  1869.     X    if (appt->flags & A_COMMENT) {
  1870.     X        fputs(inbuf, apts_file);
  1871.     X        return(ferror(apts_file));
  1872.     X    }
  1873.     X    if (appt->flags & ALL_YEARS)
  1874.     X        fputs("** ", apts_file);
  1875.     X    else if (appt->year > 99)
  1876.     X        fprintf(apts_file, "%03d ", appt->year);
  1877.     X    else
  1878.     X        fprintf(apts_file, "%02d ", appt->year);
  1879.     X    if (appt->flags & ALL_MONTHS)
  1880.     X        fputs("** ", apts_file);
  1881.     X    else
  1882.     X        fprintf(apts_file, "%02d ", one_based ? appt->month+1 : appt->month);
  1883.     X    if (appt->flags & ALL_DAYS)
  1884.     X        fputs("** ", apts_file);
  1885.     X    else if (appt->flags & EVERY_SOMEDAY) {
  1886.     X        switch (appt->flags & EVERY_SOMEDAY) {
  1887.     X            case EVERY_SUN:
  1888.     X                fputs("Su ", apts_file);
  1889.     X                break;
  1890.     X            case EVERY_MON:
  1891.     X                fputs("Mo ", apts_file);
  1892.     X                break;
  1893.     X            case EVERY_TUE:
  1894.     X                fputs("Tu ", apts_file);
  1895.     X                break;
  1896.     X            case EVERY_WED:
  1897.     X                fputs("We ", apts_file);
  1898.     X                break;
  1899.     X            case EVERY_THU:
  1900.     X                fputs("Th ", apts_file);
  1901.     X                break;
  1902.     X            case EVERY_FRI:
  1903.     X                fputs("Fr ", apts_file);
  1904.     X                break;
  1905.     X            case EVERY_SAT:
  1906.     X                fputs("Sa ", apts_file);
  1907.     X                break;
  1908.     X        }
  1909.     X    } else
  1910.     X        fprintf(apts_file, "%02d ", one_based ? appt->day : appt->day-1);
  1911.     X    if (appt->flags & A_NOTE) {
  1912.     X        appt->hour = 99;
  1913.     X        appt->minute = 0;    /* assume unmarked note */
  1914.     X    }
  1915.     X    if ((appt->flags & MARKED_NOTE) == MARKED_NOTE)
  1916.     X        appt->minute = 99;
  1917.     X    if (!(appt->flags & (ALL_DAYS|DELETED)) && appt->flags & REPEAT) {
  1918.     X        if (appt->flags & EVERY_SOMEDAY)
  1919.     X            fprintf(apts_file, "%02d %02d %02d %s ", appt->hour, appt->minute, appt->arrows, to_str(appt->repeat));
  1920.     X        else
  1921.     X            fprintf(apts_file, "%02d %02d %02d [%d] ", appt->hour, appt->minute, appt->arrows, appt->repeat);
  1922.     X    } else
  1923.     X        fprintf(apts_file, "%02d %02d %02d ", appt->hour, appt->minute, appt->arrows);
  1924.     X
  1925.     X    if (appt->flags & LOOKAHEAD)
  1926.     X        fprintf(apts_file, "<%d> ", appt->lookahead);
  1927.     X    if (appt->flags & DELETED)
  1928.     X        fprintf(apts_file, "# %s\n", appt->str);
  1929.     X    else
  1930.     X        fprintf(apts_file, "%s\n", appt->str);
  1931.     X    
  1932.     X    /* check for failure (e.g. file system full) */
  1933.     X    return(ferror(apts_file));
  1934.     X}
  1935.     X
  1936.     Xchar rptstr[10];
  1937.     X
  1938.     X/* convert repeat bit map to printable string */
  1939.     Xchar *
  1940.     Xto_str(repeat)
  1941.     Xint repeat;
  1942.     X{
  1943.     X    int i, j = 0;
  1944.     X
  1945.     X    if (repeat == ALL_WEEKS)
  1946.     X        /* if it's every week, then don't write [] spec */
  1947.     X        rptstr[0] = '\0';
  1948.     X    else {
  1949.     X        rptstr[j++] = '[';
  1950.     X        for (i=0; i<5; i++) {
  1951.     X            if (repeat & (0x1<<i)) {
  1952.     X                rptstr[j++] = i+1 + '0';
  1953.     X                rptstr[j++] = ',';
  1954.     X            }
  1955.     X        }
  1956.     X        if (repeat & LAST_WEEK) {
  1957.     X            rptstr[j++] = 'L';
  1958.     X            rptstr[j++] = ',';
  1959.     X        }
  1960.     X        rptstr[j] = '\0';
  1961.     X        rptstr[--j] = ']';
  1962.     X    }
  1963.     X    return (rptstr);
  1964.     X}
  1965.     X
  1966.     X/*
  1967.     X * Print today's appointments to stdout or mail (useful if we only have an ASCII
  1968.     X * terminal connected to our Sun). Invoked by the "-p", "-P" or "-m" options.
  1969.     X */
  1970.     Xprint_apts(level)
  1971.     Xint level;
  1972.     X{
  1973.     X    int i;
  1974.     X    FILE *output, *popen();
  1975.     X    char cmd[80], *name, *cuserid(), *format_appt();
  1976.     X    struct appt_entry tmp_apt, *sptr;
  1977.     X
  1978.     X    fix_current_day();
  1979.     X    get_day_appts();
  1980.     X    if (level == 2) {
  1981.     X        if (mailto != NULL) {
  1982.     X            name = mailto;
  1983.     X        } else if ((name = cuserid(NULL)) == NULL) {
  1984.     X            err_rpt("nobody to mail to", FATAL);
  1985.     X        }
  1986.     X        sprintf(cmd, "mail -s \"Appointments for today\" %s", name);
  1987.     X        if ((output = popen(cmd, "w")) == NULL)
  1988.     X            err_rpt("Couldn't pipe to 'mail'", FATAL);
  1989.     X    } else {
  1990.     X        output = stdout;
  1991.     X    }
  1992.     X    
  1993.     X    fprintf(output,"\n\t*** Appointments for %s %s %d, 19%02d ***\n\n", 
  1994.     X        daynames[current.tm_wday], monthnames[current.tm_mon],
  1995.     X        current.tm_mday, current.tm_year);
  1996.     X    
  1997.     X    for (i=0; i<N_SLOTS; i++) {
  1998.     X        if (i == n_tslots)
  1999.     X            /* start of notes section */
  2000.     X            fprintf(output,"\n\t\t     ===== Notes =====\n");
  2001.     X        if (slots[i].first != NULL && slots[i].count > 0) {
  2002.     X            /* at least one appt here */
  2003.     X            slots[i].cur_appt = slots[i].first;
  2004.     X            do {
  2005.     X                if (level == 3 && ((slots[i].cur_appt->flags & MARKED_NOTE) == MARKED_NOTE))
  2006.     X                    continue;
  2007.     X                if (chk_deleted(i))
  2008.     X                    continue;
  2009.     X                tmp_apt = *slots[i].cur_appt;
  2010.     X                tmp_apt.year = current.tm_year;
  2011.     X                tmp_apt.month = current.tm_mon;
  2012.     X                tmp_apt.day = current.tm_mday;
  2013.     X                fprintf(output, "%s\n", format_appt(&tmp_apt));
  2014.     X            } while ((slots[i].cur_appt = slots[i].cur_appt->next) != NULL);
  2015.     X        }
  2016.     X    }
  2017.     X    if (findex) {
  2018.     X        /* print out future appointments */
  2019.     X        fprintf(output, "\n\t\t===== Future Reminders =====\n");
  2020.     X        for (i=0; i<findex; i++)
  2021.     X            fprintf(output, "%s\n", format_appt(&future[i]));
  2022.     X    }
  2023.     X    fflush(output);
  2024.     X    if (level == 2)
  2025.     X        pclose(output);
  2026.     X}
  2027.     X
  2028.     X/*
  2029.     X * Convert from version 1 appts files to version 2 file format.
  2030.     X */
  2031.     Xver1to2()
  2032.     X{
  2033.     X    FILE *oappts, *nappts, *fp;
  2034.     X    struct appt_entry appt;
  2035.     X    int err_flag, save_base;
  2036.     X    char save_file[128];
  2037.     X    struct stat stbuf;
  2038.     X
  2039.     X    /*
  2040.     X     * The main difference is that the ver 2 files are one-based, i.e
  2041.     X     * days and months start with 1, rather than 0. Another difference
  2042.     X     * is that a hour entry of 99 is used to flag a memo entry, rather
  2043.     X     * than 00. This allows for 24-hour appointments.
  2044.     X     * Version 2 appts files are marked with a special header line
  2045.     X     * defined by the HEADER string (in ct.h).  Version 2 files
  2046.     X     * also support a "lookahead" reminder service to remind one
  2047.     X     * in advance of a future appointment.
  2048.     X     * If "save_old" is set, then any appointments for years prior
  2049.     X     * to this one are save in a special file of the form
  2050.     X     * ".appointments.YY", where YY is the year.
  2051.     X     */
  2052.     X
  2053.     X    if (read_only != 0) {
  2054.     X        err_rpt("appts file is read-only, no conversion done", NON_FATAL);
  2055.     X        return;
  2056.     X    }
  2057.     X
  2058.     X     /* open files, etc */
  2059.     X    if ((oappts = fopen(apts_pathname, "r")) == NULL) {
  2060.     X        err_rpt("can't open appts file for reading", FATAL);
  2061.     X        /* NOT REACHED */
  2062.     X     }
  2063.     X    if ((nappts = fopen(tmpapts_pathname, "w")) == NULL) {
  2064.     X        err_rpt("can't open temp file for writing", NON_FATAL);
  2065.     X        return;
  2066.     X     }
  2067.     X     /* write new header line */
  2068.     X     fputs(HEADER, nappts);
  2069.     X
  2070.     X     /* copy existing entries to the new file */
  2071.     X     save_base = one_based;
  2072.     X     while ((err_flag = get_aentry(oappts, &appt)) != EOF) {
  2073.     X        if (err_flag)
  2074.     X            continue;    /* ignore badly formatted input */
  2075.     X        if (appt.hour == 0)
  2076.     X            appt.flags |= A_NOTE;
  2077.     X        one_based = 1;        /* force new format output */
  2078.     X        if (save_old && !(appt.flags & ALL_YEARS) && (appt.year < today.tm_year)
  2079.     X           && !((appt.flags & REPEAT) && !(appt.flags & EVERY_SOMEDAY))
  2080.     X           && !(appt.flags & A_COMMENT)) {
  2081.     X            /* prepend directory info */
  2082.     X            sprintf(save_file, "%s/.appointments.%02d",
  2083.     X                apts_dir, appt.year);
  2084.     X            if (stat(save_file, &stbuf) && errno == ENOENT) {
  2085.     X                /* new file*/
  2086.     X                if ((fp = fopen(save_file, "w")) == NULL)
  2087.     X                    err_rpt("can't open save file, bailing out", FATAL);
  2088.     X                fputs(HEADER, fp);
  2089.     X                fclose(fp);
  2090.     X            }
  2091.     X            if ((fp = fopen(save_file, "a+")) == NULL)
  2092.     X                err_rpt("can't open save file, bailing out", FATAL);
  2093.     X            else {
  2094.     X                if (put_aentry(fp, &appt))
  2095.     X                    err_rpt("write to save appt file failed, bailing out", FATAL);
  2096.     X                fclose(fp);
  2097.     X            }
  2098.     X        } else {
  2099.     X            if (put_aentry(nappts, &appt))
  2100.     X                err_rpt("write to new appt file failed, bailing out", FATAL);
  2101.     X        }
  2102.     X        one_based = save_base;    /* (maybe) force old format input */
  2103.     X    }
  2104.     X    fclose(oappts);
  2105.     X    fclose(nappts);
  2106.     X    xrename(tmpapts_pathname, apts_pathname);
  2107.     X    one_based = 1;
  2108.     X    version2 = 1;
  2109.     X}
  2110.     X
  2111.     X/*
  2112.     X * Scan appointments file for outdated appointments and save them to a
  2113.     X * special file of the form ".appointments.YY", where YY is the year
  2114.     X * of that appointment.
  2115.     X */
  2116.     Xcreate_old_files()
  2117.     X{
  2118.     X    FILE *oappts, *nappts, *fp;
  2119.     X    struct appt_entry appt;
  2120.     X    int err_flag;
  2121.     X    char save_file[128];
  2122.     X    struct stat stbuf;
  2123.     X
  2124.     X    if (read_only != 0) {
  2125.     X        err_rpt("appts file is read-only, no conversion done", NON_FATAL);
  2126.     X        return;
  2127.     X    }
  2128.     X
  2129.     X     /* open files, etc */
  2130.     X    if ((oappts = fopen(apts_pathname, "r")) == NULL) {
  2131.     X        err_rpt("can't open appts file for reading", FATAL);
  2132.     X        /* NOT REACHED */
  2133.     X     }
  2134.     X    if ((nappts = fopen(tmpapts_pathname, "w")) == NULL) {
  2135.     X        err_rpt("can't open temp file for writing", NON_FATAL);
  2136.     X        return;
  2137.     X     }
  2138.     X
  2139.     X     /* copy existing entries to the tmp file, checking dates */
  2140.     X     while ((err_flag = get_aentry(oappts, &appt)) != EOF) {
  2141.     X        if (err_flag)
  2142.     X            continue;    /* ignore badly formatted input */
  2143.     X        if (!(appt.flags & A_COMMENT)
  2144.     X           && !(appt.flags & ALL_YEARS) && (appt.year < today.tm_year)
  2145.     X           && !((appt.flags & REPEAT) && !(appt.flags & EVERY_SOMEDAY))) {
  2146.     X            /* prepend directory info */
  2147.     X            sprintf(save_file, "%s/.appointments.%02d",
  2148.     X                apts_dir, appt.year);
  2149.     X            if (stat(save_file, &stbuf) && errno == ENOENT) {
  2150.     X                /* new file*/
  2151.     X                if ((fp = fopen(save_file, "w")) == NULL)
  2152.     X                    err_rpt("can't open save file, bailing out", FATAL);
  2153.     X                fputs(HEADER, fp);
  2154.     X                fclose(fp);
  2155.     X            }
  2156.     X            if ((fp = fopen(save_file, "a+")) == NULL)
  2157.     X                err_rpt("can't open save file, bailing out", FATAL);
  2158.     X            else {
  2159.     X                if (put_aentry(fp, &appt))
  2160.     X                    err_rpt("write to save appt file failed, bailing out", FATAL);
  2161.     X                fclose(fp);
  2162.     X            }
  2163.     X        } else {
  2164.     X            if (put_aentry(nappts, &appt))
  2165.     X                err_rpt("write to new appt file failed, bailing out", FATAL);
  2166.     X        }
  2167.     X    }
  2168.     X    fclose(oappts);
  2169.     X    fclose(nappts);
  2170.     X    xrename(tmpapts_pathname, apts_pathname);
  2171.     X}
  2172.     X
  2173.     X/*
  2174.     X * convert appt entry to ASCII string for display with date, time and msg
  2175.     X */
  2176.     Xchar *
  2177.     Xformat_appt(appt)
  2178.     Xstruct appt_entry *appt;
  2179.     X{
  2180.     X    int e_hour, e_minutes, duration;
  2181.     X    struct tm Save;
  2182.     X
  2183.     X    if (appt->arrows > 0) {
  2184.     X        duration = appt->arrows + 1;
  2185.     X        e_hour = appt->hour + duration/2;
  2186.     X        e_minutes = appt->minute + ((duration%2) * 30);
  2187.     X    } else {
  2188.     X        e_hour = appt->hour;
  2189.     X        e_minutes = appt->minute + 30;
  2190.     X    }
  2191.     X    if (e_minutes == 60) {
  2192.     X        e_minutes = 0;
  2193.     X        ++e_hour;
  2194.     X    }
  2195.     X    /* get day of week */
  2196.     X    Save = current;
  2197.     X    current.tm_year = appt->year;
  2198.     X    current.tm_mon = appt->month;
  2199.     X    current.tm_mday = appt->day;
  2200.     X    fix_current_day();
  2201.     X
  2202.     X    if (appt->flags & A_NOTE) {
  2203.     X        /* note */
  2204.     X        if (appt->flags & ALL_YEARS)
  2205.     X            sprintf(strbuf,"%3.3s %2d/%02d    --  %s",
  2206.     X                daynames[current.tm_wday], appt->month+1,
  2207.     X                appt->day, appt->str);
  2208.     X        else if (appt->year > 99)
  2209.     X            sprintf(strbuf,"%3.3s %2d/%02d/%02d --  %s",
  2210.     X                daynames[current.tm_wday], appt->month+1,
  2211.     X                appt->day, appt->year-100, appt->str);
  2212.     X        else
  2213.     X            sprintf(strbuf,"%3.3s %2d/%02d/%02d --  %s",
  2214.     X                daynames[current.tm_wday], appt->month+1,
  2215.     X                appt->day, appt->year, appt->str);
  2216.     X    } else
  2217.     X        /* standard appointment */
  2218.     X        sprintf(strbuf,"%3.3s %2d/%02d/%02d -- %2d:%02d to %2d:%02d   %s",
  2219.     X            daynames[current.tm_wday], appt->month+1,
  2220.     X            appt->day, appt->year, appt->hour, appt->minute,
  2221.     X            e_hour, e_minutes, appt->str);
  2222.     X
  2223.     X    current = Save;
  2224.     X    return(strbuf);
  2225.     X}
  2226.     X
  2227.     X/*
  2228.     X * convert appt entry to ASCII string for display with time and msg
  2229.     X */
  2230.     Xchar *
  2231.     Xformat_appt_nd(appt)
  2232.     Xstruct appt_entry *appt;
  2233.     X{
  2234.     X    int e_hour, e_minutes, duration;
  2235.     X    struct tm Save;
  2236.     X
  2237.     X    if (appt->arrows > 0) {
  2238.     X        duration = appt->arrows + 1;
  2239.     X        e_hour = appt->hour + duration/2;
  2240.     X        e_minutes = appt->minute + ((duration%2) * 30);
  2241.     X    } else {
  2242.     X        e_hour = appt->hour;
  2243.     X        e_minutes = appt->minute + 30;
  2244.     X    }
  2245.     X    if (e_minutes == 60) {
  2246.     X        e_minutes = 0;
  2247.     X        ++e_hour;
  2248.     X    }
  2249.     X
  2250.     X    if (appt->flags & A_NOTE) {
  2251.     X        /* note */
  2252.     X        sprintf(strbuf,"%s", appt->str);
  2253.     X    } else
  2254.     X        /* standard appointment */
  2255.     X        sprintf(strbuf,"%2d:%02d to %2d:%02d   %s",
  2256.     X            appt->hour, appt->minute, e_hour, e_minutes, appt->str);
  2257.     X
  2258.     X    return(strbuf);
  2259.     X}
  2260.     X
  2261.     X/*
  2262.     X * parse the date on the given tring and reset the "current"
  2263.     X * date to reflect that date. The date may take the form of a
  2264.     X * day name (e.g. Tu, Tue, Tuesday) or a date in m/d/y format
  2265.     X * where the month and/or year may be missing (e.g. 27 = 27th
  2266.     X * of this month, 8/27 = August 27 of this year, 8/27/89 =
  2267.     X * August 27 of 1989. If 'cmdline' is true, then the string
  2268.     X * came from the command line '-d' option.
  2269.     X */
  2270.     Xint
  2271.     Xparse_date(str, cmdline)
  2272.     Xchar *str;
  2273.     Xint cmdline;
  2274.     X{
  2275.     X    char c[4];
  2276.     X    int i, dow = -1, m = -1, d = -1, y = -1;
  2277.     X
  2278.     X    if (isdigit(*str)) {
  2279.     X        /* must be a m/d/y date */
  2280.     X        /* assume it's a month first */
  2281.     X        m = *str++ - '0';
  2282.     X        if (isdigit(*str))
  2283.     X            m = m*10 + *str++ - '0';
  2284.     X        if (!*str) {
  2285.     X            /* no more chars => day only */
  2286.     X            d = m;
  2287.     X            m = -1;
  2288.     X        } else if (*str++ != '/') {
  2289.     X            if (cmdline)
  2290.     X                err_rpt("badly formed date for -d option (ignored)", NON_FATAL);
  2291.     X            else
  2292.     X                err_rpt("badly formed date - please reenter", NON_FATAL);
  2293.     X            return(1);
  2294.     X        } else {
  2295.     X            d = *str++ - '0';
  2296.     X            if (isdigit(*str))
  2297.     X                d = d*10 + *str++ - '0';
  2298.     X            if (*str++ == '/') {
  2299.     X                /* year also specified */
  2300.     X                y = *str++ - '0';
  2301.     X                if (isdigit(*str)) {
  2302.     X                    y = y*10 + *str++ - '0';
  2303.     X                    if (*str && isdigit(*str))
  2304.     X                        y = y*10 + *str - '0';
  2305.     X                }
  2306.     X            }
  2307.     X        }
  2308.     X        if (y > 0)
  2309.     X            current.tm_year = y;
  2310.     X        if (m > 0)
  2311.     X            current.tm_mon = m - 1;
  2312.     X        if (d > 0)
  2313.     X            current.tm_mday = d;
  2314.     X        fix_current_day();
  2315.     X    } else {
  2316.     X        /* day of week */
  2317.     X        /* check for day names */
  2318.     X        c[0] = islower(*str) ? toupper(*str) : *str;
  2319.     X        ++str;
  2320.     X        c[1] = islower(*str) ? toupper(*str) : *str;
  2321.     X        c[2] = '\0';
  2322.     X        for (i=0; i<7; i++) {
  2323.     X            if (!strcmp(c, dayname[i])) {
  2324.     X                dow = i;
  2325.     X                break;
  2326.     X            }
  2327.     X        }
  2328.     X        if (dow >= 0) {
  2329.     X            /* match found */
  2330.     X            current.tm_mday += dow - current.tm_wday;
  2331.     X            fix_current_day();
  2332.     X        } else {
  2333.     X            if (cmdline)
  2334.     X                err_rpt("badly formed date for -d option (ignored)", NON_FATAL);
  2335.     X            else
  2336.     X                err_rpt("badly formed date - please reenter", NON_FATAL);
  2337.     X            return(1);
  2338.     X        }
  2339.     X    }
  2340.     X    return(0);
  2341.     X}
  2342.     X
  2343.     X#ifndef NO_PRINTER
  2344.     X/*
  2345.     X * Print to Postscript compatable printer.  If we are displaying
  2346.     X * the day or week page, then create a raster file of the canvas and
  2347.     X * feed it to a raster->ps filter (sun2ps).  If on a month page, then
  2348.     X * print a pretty month calendar with appts written in (as best
  2349.     X * can be).
  2350.     X */
  2351.     Xprint_calendar(file_type)
  2352.     Xint file_type;
  2353.     X{
  2354.     X    Pixrect *save_pr;
  2355.     X    char prntcmd[64];
  2356.     X    int type = RT_STANDARD;
  2357.     X    int copy_flag = TRUE;
  2358.     X    Rect *rect;
  2359.     X    struct pr_prpos where;
  2360.     X    char buf[128], *cuserid();
  2361.     X    FILE *fp, *pfp;
  2362.     X
  2363.     X    lock_cursors();
  2364.     X    working(TRUE);
  2365.     X    sprintf(buf, "Appointments file \"%s\" printed for %s on %s", apts_pathname, cuserid(NULL), todays_date);
  2366.     X    if (mainsw_state != DISPLAYING_MONTH) {
  2367.     X        if ((fp = fopen(rasfile, "w")) != NULL) {
  2368.     X            rect = (Rect *) window_get(canvas, WIN_RECT);
  2369.     X            save_pr = mem_create(rect->r_width, rect->r_height+3*sfont->pf_defaultsize.y, 1);
  2370.     X            pr_rop(save_pr,0,0,rect->r_width-3,rect->r_height,PIX_SRC,main_pixwin->pw_prretained,0,0);
  2371.     X            where.pr = save_pr;
  2372.     X            where.pos.x = 6 * font->pf_defaultsize.x;
  2373.     X            where.pos.y = rect->r_height + 2*sfont->pf_defaultsize.y;
  2374.     X            pf_text(where, PIX_SRC, sfont, buf);
  2375.     X            pr_dump(save_pr, fp, NULL, type, copy_flag);
  2376.     X            fclose(fp);
  2377.     X            if (file_type == PR_POSTSCRIPT) {
  2378.     X                if ((pfp = fopen(psfile, "w")) != NULL) {
  2379.     X                    fp = fopen(rasfile, "r");
  2380.     X                    /* ras2ps closes the files that
  2381.     X                     * we opened here.
  2382.     X                     */
  2383.     X                    ras2ps(fp, pfp);
  2384.     X                    sprintf(prntcmd, "%s %s", printer, psfile);
  2385.     X                    system(prntcmd);
  2386.     X                    unlink(psfile);
  2387.     X                } else
  2388.     X                    err_rpt("can't open tmp ps file", NON_FATAL);
  2389.     X            } else {
  2390.     X                sprintf(prntcmd, "%s %s", printer, rasfile);
  2391.     X                system(prntcmd);
  2392.     X            }
  2393.     X            pr_destroy(save_pr);
  2394.     X            unlink(rasfile);
  2395.     X        } else
  2396.     X            err_rpt("can't open tmp raster file", NON_FATAL);
  2397.     X    } else if (mainsw_state == DISPLAYING_MONTH) {
  2398.     X        if (file_type != PR_POSTSCRIPT) {
  2399.     X            err_rpt("only PostScript output available for month printout", NON_FATAL);
  2400.     X        } else {
  2401.     X            if ((pfp = fopen(psfile, "w")) != NULL) {
  2402.     X                print_month(pfp);
  2403.     X                fclose(pfp);
  2404.     X                sprintf(prntcmd, "%s %s", printer, psfile);
  2405.     X                system(prntcmd);
  2406.     X                unlink(psfile);
  2407.     X            } else
  2408.     X                err_rpt("can't open tmp ps file", NON_FATAL);
  2409.     X        }
  2410.     X    }
  2411.     X    working(FALSE);
  2412.     X    unlock_cursors();
  2413.     X}
  2414.     X#endif    /* NO_PRINTER */
  2415.     X
  2416.     X/* set error logging flag */
  2417.     Xerr2console(state)
  2418.     Xint state;
  2419.     X{
  2420.     X    /*
  2421.     X     * if TRUE, forces error messages to the console, even
  2422.     X     * if the base frame is running
  2423.     X     */
  2424.     X    log_to_console = state;
  2425.     X}
  2426.     X
  2427.     X/*
  2428.     X * Error reporting. Try first to put message in a popup frame, then
  2429.     X * the console, then stderr as a last resort.
  2430.     X */
  2431.     Xerr_rpt(errstr, fatal_flag)
  2432.     Xchar *errstr;
  2433.     Xint fatal_flag;
  2434.     X{
  2435.     X    FILE    *f;
  2436.     X    int    closed;
  2437.     X
  2438.     X    closed = (int) window_get(frame, FRAME_CLOSED);
  2439.     X    if (frame && !log_to_console && !closed) {
  2440.     X        /* base frame exists */
  2441.     X        create_prompt_frame(errstr, FALSE);
  2442.     X        (void) window_loop(prompt_frame);
  2443.     X        window_set(prompt_frame, WIN_SHOW, FALSE, 0);
  2444.     X    } else if ((f=fopen("/dev/console", "w")) != NULL) {
  2445.     X        fprintf(f, "%s: %s\n", progname, errstr);
  2446.     X        fclose(f);
  2447.     X    } else
  2448.     X        fprintf(stderr, "%s: %s\n", progname, errstr);
  2449.     X    if (fatal_flag)
  2450.     X        exit(1);
  2451.     X}
  2452.     X
  2453.     X/* Clean-up */
  2454.     Xcleanup()
  2455.     X{
  2456.     X    if (day_is_open)
  2457.     X        close_day();
  2458.     X
  2459.     X    /* create outdated include files (if necessary) */
  2460.     X    if (save_old)
  2461.     X        create_old_files();
  2462.     X            
  2463.     X    /* delete tmp file */
  2464.     X    if (access(tmpapts_pathname, R_OK) == 0 && unlink(tmpapts_pathname) < 0)
  2465.     X        perror(tmpapts_pathname);
  2466.     X}
  2467.     X
  2468.     Xchar sysbuf[512];
  2469.     X
  2470.     X/* Rename files, copying if necessary */
  2471.     Xxrename(from, to)
  2472.     Xchar *from, *to;
  2473.     X{
  2474.     X    if (rename(from, to) == -1) {
  2475.     X        /* rename sys call fialed, try doing a copy */
  2476.     X        sprintf(sysbuf, "cp %s %s", from, to);
  2477.     X        if (system(sysbuf) != 0)
  2478.     X            err_rpt("couldn't rename/copy tmp file", NON_FATAL);
  2479.     X    }
  2480.     X}
  2481. SHAR_EOF
  2482. if test 31671 -ne "`wc -c < 'utils.c'`"
  2483. then
  2484.     echo shar: error transmitting "'utils.c'" '(should have been 31671 characters)'
  2485. fi
  2486. fi # end of overwriting check
  2487. echo shar: extracting "'version.c'" '(946 characters)'
  2488. if test -f 'version.c'
  2489. then
  2490.     echo shar: will not over-write existing file "'version.c'"
  2491. else
  2492. sed 's/^    X//' << \SHAR_EOF > 'version.c'
  2493.     X/*
  2494.     X * $Header: version.c,v 2.3 89/05/16 16:31:58 billr Exp $
  2495.     X */
  2496.     X/*
  2497.     X * version.c - current version of calentool program
  2498.     X *
  2499.     X * calentool - a year/month/week/day-at-a-glance calendar for Sun workstations.
  2500.     X *
  2501.     X * Author: Philip Heller, Sun Microsystems. Inc. <terrapin!heller@sun.com>
  2502.     X *
  2503.     X * Original source Copyright (C) 1987, Sun Microsystems, Inc.
  2504.     X *    All Rights Reserved
  2505.     X * Permission is hereby granted to use and modify this program in source
  2506.     X * or binary form as long as it is not sold for profit and this copyright
  2507.     X * notice remains intact.
  2508.     X *
  2509.     X *
  2510.     X * Changes/additions by: Bill Randle, Tektronix, Inc. <billr@saab.CNA.TEK.COM>
  2511.     X *
  2512.     X * Changes and additions Copyright (C) 1988, 1989 Tektronix, Inc.
  2513.     X *    All Rights Reserved
  2514.     X * Permission is hereby granted to use and modify the modifications in source
  2515.     X * or binary form as long as they are not sold for profit and this copyright
  2516.     X * notice remains intact.
  2517.     X */
  2518.     X
  2519.     Xchar version[] = "Calendar Tool V2.1p2";
  2520. SHAR_EOF
  2521. if test 946 -ne "`wc -c < 'version.c'`"
  2522. then
  2523.     echo shar: error transmitting "'version.c'" '(should have been 946 characters)'
  2524. fi
  2525. fi # end of overwriting check
  2526. echo shar: extracting "'week.cursor'" '(284 characters)'
  2527. if test -f 'week.cursor'
  2528. then
  2529.     echo shar: will not over-write existing file "'week.cursor'"
  2530. else
  2531. sed 's/^    X//' << \SHAR_EOF > 'week.cursor'
  2532.     X/* $Header: week.cursor,v 2.1 89/05/09 14:31:09 billr Exp $ */
  2533.     X/* Format_version=1, Width=16, Height=16, Depth=1, Valid_bits_per_item=16
  2534.     X */
  2535.     X        0x4004, 0x2008, 0x1FF0, 0x1010, 0x17D0, 0x1550, 0x1550, 0x1550,
  2536.     X        0x1550, 0x1550, 0x1550, 0x17D0, 0x1010, 0x1FF0, 0x2008, 0x4004
  2537. SHAR_EOF
  2538. if test 284 -ne "`wc -c < 'week.cursor'`"
  2539. then
  2540.     echo shar: error transmitting "'week.cursor'" '(should have been 284 characters)'
  2541. fi
  2542. fi # end of overwriting check
  2543. echo shar: extracting "'wevent.c'" '(3699 characters)'
  2544. if test -f 'wevent.c'
  2545. then
  2546.     echo shar: will not over-write existing file "'wevent.c'"
  2547. else
  2548. sed 's/^    X//' << \SHAR_EOF > 'wevent.c'
  2549.     X/*
  2550.     X * $Header: wevent.c,v 2.1 89/05/09 14:19:57 billr Exp $
  2551.     X */
  2552.     X/*
  2553.     X * wevent.c
  2554.     X *
  2555.     X * Author: Philip Heller, Sun Microsystems. Inc. <terrapin!heller@sun.com>
  2556.     X *
  2557.     X * Original source Copyright (C) 1987, Sun Microsystems, Inc.
  2558.     X *    All Rights Reserved
  2559.     X * Permission is hereby granted to use and modify this program in source
  2560.     X * or binary form as long as it is not sold for profit and this copyright
  2561.     X * notice remains intact.
  2562.     X *
  2563.     X *
  2564.     X * Changes/additions by: Bill Randle, Tektronix, Inc. <billr@saab.CNA.TEK.COM>
  2565.     X *
  2566.     X * Changes and additions Copyright (C) 1988, 1989 Tektronix, Inc.
  2567.     X *    All Rights Reserved
  2568.     X * Permission is hereby granted to use and modify the modifications in source
  2569.     X * or binary form as long as they are not sold for profit and this copyright
  2570.     X * notice remains intact.
  2571.     X */
  2572.     X/********************************************************
  2573.     X *                            *
  2574.     X *      Week event routines for main subwindow.        *
  2575.     X *                            *
  2576.     X ********************************************************/
  2577.     X
  2578.     X
  2579.     X#include <stdio.h>
  2580.     X#include <suntool/sunview.h>
  2581.     X#include <suntool/canvas.h>
  2582.     X#include <suntool/panel.h>
  2583.     X#include "ct.h"
  2584.     X#include "event.h"
  2585.     X
  2586.     Xextern Frame prompt_frame;
  2587.     X
  2588.     Xweek_inputevent(canvas, event) 
  2589.     XCanvas canvas;
  2590.     XEvent *event;
  2591.     X{ 
  2592.     X    int i = -1;
  2593.     X    int x, y;
  2594.     X    static int day_chosen_from_week;
  2595.     X
  2596.     X    /* translate coordinates to pixwin space */
  2597.     X    event = canvas_window_event(canvas, event);
  2598.     X        if (event_id(event) != MS_LEFT)        /* Ignore kbd events. */
  2599.     X                return;
  2600.     X
  2601.     X        if (event_is_down(event)) {               /* Button down. */
  2602.     X        day_chosen_from_week = -1;
  2603.     X                for (i=0; i<nr_weekdays; i++) {
  2604.     X            x = event_x(event);
  2605.     X            y = event_y(event);
  2606.     X                        if (x >= week_boxes[i].wday_pos.left && x <= week_boxes[i].wday_pos.right &&
  2607.     X                            y >= week_boxes[i].wday_pos.top && y <= week_boxes[i].wday_pos.bottom) {
  2608.     X                day_chosen_from_week = i;
  2609.     X                pw_write(main_pixwin, week_boxes[i].wday_pos.left+1,
  2610.     X                                  week_boxes[i].wday_pos.top+1, weekslot_width-2,
  2611.     X                                  (weekslot_height)*N_SLOTS-2, PIX_NOT(PIX_DST), NULL,0,0);
  2612.     X                return;
  2613.     X            }
  2614.     X            /* is cursor inside a "more" button ? */
  2615.     X            if (x>=week_boxes[i].moreb_pos.left && x<=week_boxes[i].moreb_pos.right &&
  2616.     X                y>=week_boxes[i].moreb_pos.top && y<=week_boxes[i].moreb_pos.bottom) {
  2617.     X                if (week_boxes[i].more) {
  2618.     X                    /* "more" button is active */
  2619.     X                    day_chosen_from_week = i+10;
  2620.     X                    return;
  2621.     X                }
  2622.     X            }
  2623.     X        }
  2624.     X        return;            /* Mouse wasn't in any square. */
  2625.     X    } else {                        /* Button up. */
  2626.     X        if (day_chosen_from_week == -1)
  2627.     X            return;
  2628.     X        if (day_chosen_from_week >= 10) {
  2629.     X            /* more button selected */
  2630.     X            /* print info message */
  2631.     X            do_more_msg(day_chosen_from_week-10);
  2632.     X            return;
  2633.     X        }
  2634.     X        current.tm_mday -= current.tm_wday;
  2635.     X        current.tm_mday += day_chosen_from_week;
  2636.     X        fix_current_day();
  2637.     X        if (nr_weekdays == 5) {
  2638.     X            current.tm_mday++;
  2639.     X            fix_current_day();
  2640.     X        }
  2641.     X        mainsw_state = DISPLAYING_DAY;
  2642.     X        window_set(canvas, WIN_CURSOR, day_cursor, 0);
  2643.     X        draw_day();
  2644.     X    }
  2645.     X}
  2646.     X
  2647.     X/* display more popup message */
  2648.     Xdo_more_msg(i)
  2649.     Xint i;
  2650.     X{
  2651.     X    int width, height, left, bottom;
  2652.     X
  2653.     X    /* get x,y position of canvas window on the screen so we
  2654.     X     * can center this one in it.
  2655.     X     */
  2656.     X    create_prompt_frame("Select this day to view additional appointments.", FALSE);
  2657.     X    width = (int) window_get(prompt_frame, WIN_WIDTH);
  2658.     X    height = (int) window_get(prompt_frame, WIN_HEIGHT);
  2659.     X    left = (week_boxes[i].wday_pos.right + week_boxes[i].wday_pos.left - width) / 2;
  2660.     X    bottom = (week_boxes[i].wday_pos.top + week_boxes[i].wday_pos.bottom - height) / 2;
  2661.     X    window_set(prompt_frame, WIN_X, left, WIN_Y, bottom, 0);
  2662.     X    (void) window_loop(prompt_frame);
  2663.     X    window_set(prompt_frame, WIN_SHOW, FALSE, 0);
  2664.     X}
  2665. SHAR_EOF
  2666. if test 3699 -ne "`wc -c < 'wevent.c'`"
  2667. then
  2668.     echo shar: error transmitting "'wevent.c'" '(should have been 3699 characters)'
  2669. fi
  2670. fi # end of overwriting check
  2671. echo shar: extracting "'wpaint.c'" '(7846 characters)'
  2672. if test -f 'wpaint.c'
  2673. then
  2674.     echo shar: will not over-write existing file "'wpaint.c'"
  2675. else
  2676. sed 's/^    X//' << \SHAR_EOF > 'wpaint.c'
  2677.     X/*
  2678.     X * $Header: wpaint.c,v 2.1 89/05/09 14:20:03 billr Exp $
  2679.     X */
  2680.     X/*
  2681.     X * wpaint.c
  2682.     X *
  2683.     X * Author: Philip Heller, Sun Microsystems. Inc. <terrapin!heller@sun.com>
  2684.     X *
  2685.     X * Original source Copyright (C) 1987, Sun Microsystems, Inc.
  2686.     X *    All Rights Reserved
  2687.     X * Permission is hereby granted to use and modify this program in source
  2688.     X * or binary form as long as it is not sold for profit and this copyright
  2689.     X * notice remains intact.
  2690.     X *
  2691.     X *
  2692.     X * Changes/additions by: Bill Randle, Tektronix, Inc. <billr@saab.CNA.TEK.COM>
  2693.     X *
  2694.     X * Changes and additions Copyright (C) 1988, 1989 Tektronix, Inc.
  2695.     X *    All Rights Reserved
  2696.     X * Permission is hereby granted to use and modify the modifications in source
  2697.     X * or binary form as long as they are not sold for profit and this copyright
  2698.     X * notice remains intact.
  2699.     X */
  2700.     X/***************************************************
  2701.     X *                           *
  2702.     X *    Artistic routines that draw in the main    *
  2703.     X * subwindow for the week display.           *
  2704.     X *                           *
  2705.     X ***************************************************/
  2706.     X
  2707.     X#include <suntool/sunview.h>
  2708.     X#include <suntool/canvas.h>
  2709.     X#include <ctype.h>
  2710.     X#include <stdio.h>
  2711.     X#include "ct.h"
  2712.     X#include "paint.h"
  2713.     X
  2714.     Xextern int week_message_size;
  2715.     X
  2716.     X/*
  2717.     X * Routine to draw "Week-at-a-Glance".
  2718.     X */
  2719.     X
  2720.     Xdraw_week()
  2721.     X{
  2722.     X    struct tm Save;
  2723.     X
  2724.     X    lock_cursors();
  2725.     X    /* destory future appts popup, if it exists */
  2726.     X    if (fframe) {
  2727.     X        window_destroy(fframe);
  2728.     X        fframe = 0;
  2729.     X    }
  2730.     X    fix_current_day();
  2731.     X    Save = current;
  2732.     X    current.tm_mday -= current.tm_wday; /* Sunday of this week */
  2733.     X    fix_current_day();
  2734.     X    if (nr_weekdays < 7) {
  2735.     X        current.tm_mday++;
  2736.     X        fix_current_day();
  2737.     X    }
  2738.     X    working(TRUE);
  2739.     X    get_week_appts();
  2740.     X    working(FALSE);
  2741.     X    pw_batch_on(main_pixwin);
  2742.     X    paint_week_outline();
  2743.     X    paint_week_trim();
  2744.     X    working(TRUE);
  2745.     X    draw_week_appts();
  2746.     X    pw_batch_off(main_pixwin);
  2747.     X    current = Save;
  2748.     X    get_day_appts();
  2749.     X    working(FALSE);
  2750.     X    unlock_cursors();
  2751.     X}
  2752.     X
  2753.     X
  2754.     X/* Paint the outline for "Week-at-a-Glance". */
  2755.     Xpaint_week_outline()
  2756.     X{
  2757.     X    Rect *rect;
  2758.     X        int x, y, i, j, colx;
  2759.     X 
  2760.     X        rect = (Rect *) window_get(canvas, WIN_RECT);
  2761.     X        pw_writebackground(main_pixwin,0,0,rect->r_width,rect->r_height,PIX_CLR);
  2762.     X        startx = (rect->r_width - nr_weekdays*weekslot_width) / 2;
  2763.     X    starty = 10 + (rect->r_height - (N_SLOTS*(weekslot_height+1))) / 2;
  2764.     X 
  2765.     X    First = current;
  2766.     X        for (i=0; i<nr_weekdays; i++) {
  2767.     X                x = startx + i*weekslot_width;
  2768.     X        y = starty;
  2769.     X                week_boxes[i].wday_pos.left = x;
  2770.     X                week_boxes[i].wday_pos.top = y;
  2771.     X                week_boxes[i].wday_pos.right = x + weekslot_width;
  2772.     X                week_boxes[i].wday_pos.bottom = starty + N_SLOTS*weekslot_height;
  2773.     X        week_boxes[i].moreb_pos.left = x + (weekslot_width - morebutton->pr_size.x) / 2;
  2774.     X        week_boxes[i].moreb_pos.top = week_boxes[i].wday_pos.bottom + font->pf_defaultsize.y + font->pf_defaultsize.y/2;
  2775.     X        week_boxes[i].moreb_pos.right = week_boxes[i].moreb_pos.left + morebutton->pr_size.x;
  2776.     X        week_boxes[i].moreb_pos.bottom = week_boxes[i].moreb_pos.top + morebutton->pr_size.y;
  2777.     X                for (j=0; j<N_SLOTS; j++) {
  2778.     X            if (ymd_compare(today, current) == 0)
  2779.     X                pw_write(main_pixwin,x,y,weekslot_width,
  2780.     X                  weekslot_height,PIX_SRC,weekslot_td_pr,0,0);
  2781.     X            else
  2782.     X                pw_write(main_pixwin,x,y,weekslot_width,
  2783.     X                  weekslot_height,PIX_SRC,weekslot_pr,0,0);
  2784.     X                        y += weekslot_height;
  2785.     X        }
  2786.     X        current.tm_mday++;
  2787.     X        fix_current_day();
  2788.     X        }
  2789.     X    pw_vector(main_pixwin,startx,starty,startx+nr_weekdays*weekslot_width,starty,PIX_SET,1);
  2790.     X        pw_vector(main_pixwin,startx,y-1,startx+nr_weekdays*weekslot_width,y-1,PIX_SET,1);
  2791.     X    current = First;
  2792.     X    sun_moon_buttons(FALSE);
  2793.     X    print_button(TRUE);
  2794.     X}
  2795.     X
  2796.     X
  2797.     Xpaint_week_trim()
  2798.     X{
  2799.     X    int i, j, x, y, month, day, rightx;
  2800.     X        char c[7];
  2801.     X        
  2802.     X    First = current;
  2803.     X        c[3] = '\0';            /* Mon Tue Wed Thu Fri */
  2804.     X        for (i=0; i<nr_weekdays; i++) {
  2805.     X                x = startx + i*weekslot_width + (weekslot_width - 2*(font->pf_defaultsize.x+2))/2;
  2806.     X        sprintf(c, "%3.3s", daynames[First.tm_wday + i]);
  2807.     X                pw_text(main_pixwin, x, starty-5, PIX_SRC, font, c);
  2808.     X        }
  2809.     X        
  2810.     X        y = starty + weekslot_height - 4;
  2811.     X        rightx = startx + nr_weekdays*weekslot_width + 10;
  2812.     X    for (i=0; i<N_SLOTS; i++) {
  2813.     X        if (i < n_tslots) {
  2814.     X            sprintf(c, "%2d:%s",
  2815.     X                (START_HOUR+(i/2))%12 == 0 ? 12 : (START_HOUR+(i/2))%12,
  2816.     X                i%2 == 0 ? "00" : "30");
  2817.     X        } else if (i == n_tslots) {
  2818.     X            sprintf(c, "Notes");
  2819.     X        } else {
  2820.     X            sprintf(c, "     ");
  2821.     X        }
  2822.     X                pw_text(main_pixwin, startx-6*font->pf_defaultsize.x, y, PIX_SRC, font, c);
  2823.     X                pw_text(main_pixwin, rightx, y, PIX_SRC, font, c);
  2824.     X                y += weekslot_height;
  2825.     X    }
  2826.     X
  2827.     X        x = startx + (weekslot_width - 7*(font->pf_defaultsize.x+2))/2 + font->pf_defaultsize.x+7;
  2828.     X
  2829.     X    sprintf(c, "%d", 1900 + current.tm_year);
  2830.     X    pw_text(main_pixwin, startx-2*font->pf_defaultsize.x, y+weekslot_height, PIX_SRC, font, c);
  2831.     X
  2832.     X    /* display week dates (month, day) */
  2833.     X        for (i=0; i<nr_weekdays; i++) {
  2834.     X        sprintf(c, "%3.3s %2d",
  2835.     X            monthnames[current.tm_mon], current.tm_mday);
  2836.     X        pw_text(main_pixwin, x, y, PIX_SRC, font, c);
  2837.     X                x += weekslot_width;
  2838.     X        current.tm_mday++;
  2839.     X        fix_current_day();
  2840.     X        }
  2841.     X    current = First;
  2842.     X    fix_current_day();
  2843.     X}       
  2844.     X
  2845.     X
  2846.     Xget_week_appts()
  2847.     X{
  2848.     X    int i, j, save_read;
  2849.     X    struct tm Current;
  2850.     X
  2851.     X    save_read = read_only;
  2852.     X    read_only = 1;
  2853.     X    Current = current;
  2854.     X    for (i=0; i<nr_weekdays; i++) {
  2855.     X        get_day_appts();    /* fills in slots[] array */
  2856.     X        for (j=0; j<N_SLOTS; j++)
  2857.     X            week_boxes[i].weekslots[j] = slots[j];
  2858.     X        current.tm_mday++;
  2859.     X        fix_current_day();
  2860.     X    }
  2861.     X    read_only = save_read;
  2862.     X    current = Current;
  2863.     X    fix_current_day();
  2864.     X}                       
  2865.     X
  2866.     X/* draw in week appointments */
  2867.     Xdraw_week_appts()
  2868.     X{
  2869.     X    int index, slotno;
  2870.     X    struct appt_entry *aptr, *optr;
  2871.     X
  2872.     X    for (index=0; index<nr_weekdays; index++) {
  2873.     X        x_coord = week_boxes[index].wday_pos.left;
  2874.     X        for (slotno=0; slotno<N_SLOTS; slotno++) {
  2875.     X            y_coord = week_boxes[index].wday_pos.top + slotno*weekslot_height;
  2876.     X            if (week_boxes[index].weekslots[slotno].count > 0) {
  2877.     X                switch (week_boxes[index].weekslots[slotno].active) {
  2878.     X                    case ACTIVE:
  2879.     X                        write_week_str(index, slotno);
  2880.     X                        break;
  2881.     X                    case ARROW_SHAFT:
  2882.     X                        pw_write(main_pixwin, x_coord+1, y_coord+1,
  2883.     X                          weekslot_width-2, weekslot_height-2, PIX_SRC|PIX_DST,
  2884.     X                        weekarrowshaft_pr, 0, 0);
  2885.     X                        break;
  2886.     X                    case ARROW_HEAD:
  2887.     X                        pw_write(main_pixwin, x_coord+1, y_coord+1, weekslot_width-2,
  2888.     X                          weekslot_height-2, PIX_SRC|PIX_DST, weekarrowhead_pr, 0, 0);
  2889.     X                        break;
  2890.     X                    case INACTIVE:
  2891.     X                        break;
  2892.     X                }
  2893.     X            }
  2894.     X            /* free memory alloc'd for appts */
  2895.     X            if (week_boxes[index].weekslots[slotno].first)
  2896.     X                for (aptr=week_boxes[index].weekslots[slotno].first; aptr; ) {
  2897.     X                    optr = aptr;
  2898.     X                    aptr = aptr->next;
  2899.     X                    free(optr);
  2900.     X                }
  2901.     X        }
  2902.     X        wmore_check(index);
  2903.     X    }
  2904.     X}
  2905.     X
  2906.     Xwrite_week_str(day, bi)
  2907.     Xint day;
  2908.     Xint bi;
  2909.     X{
  2910.     X    char slot_str[MAX_STRLEN];
  2911.     X    char *ptr;
  2912.     X    int strl;
  2913.     X
  2914.     X    strl = strlen(week_boxes[day].weekslots[bi].cur_appt->str);
  2915.     X    if (strl <= week_message_size)
  2916.     X        strcpy(slot_str, week_boxes[day].weekslots[bi].cur_appt->str);
  2917.     X    else {
  2918.     X        /* show leading part */
  2919.     X        
  2920.     X        strncpy(slot_str, week_boxes[day].weekslots[bi].cur_appt->str, week_message_size);
  2921.     X        slot_str[week_message_size+1] = '\0';
  2922.     X    }
  2923.     X    pw_write(main_pixwin, x_coord+1, y_coord+1, weekslot_width-2,
  2924.     X        weekslot_height-2, PIX_SET, NULL, 0, 0);
  2925.     X    pw_text(main_pixwin, x_coord+4, y_coord+font->pf_defaultsize.y, PIX_NOT(PIX_SRC),
  2926.     X        font, slot_str);
  2927.     X}
  2928.     X
  2929.     X/* display "more" button if necessary */
  2930.     Xwmore_check(day)
  2931.     Xint day;
  2932.     X{
  2933.     X    int i, more = 0;
  2934.     X    int x, y;
  2935.     X
  2936.     X    x = morebutton->pr_size.x;
  2937.     X    y = morebutton->pr_size.y;
  2938.     X    for (i=0; i<N_SLOTS; i++)
  2939.     X        if (week_boxes[day].weekslots[i].count > 1) {
  2940.     X            more = 1;
  2941.     X            break;
  2942.     X        }
  2943.     X    if (more) {
  2944.     X        week_boxes[day].more = 1;
  2945.     X        /* display more button to bottom of slot */
  2946.     X        pw_write(main_pixwin, week_boxes[day].moreb_pos.left,
  2947.     X            week_boxes[day].moreb_pos.top,
  2948.     X            x, y, PIX_SRC, morebutton, 0, 0);
  2949.     X    } else
  2950.     X        week_boxes[day].more = 0;
  2951.     X}
  2952.     X
  2953. SHAR_EOF
  2954. if test 7846 -ne "`wc -c < 'wpaint.c'`"
  2955. then
  2956.     echo shar: error transmitting "'wpaint.c'" '(should have been 7846 characters)'
  2957. fi
  2958. fi # end of overwriting check
  2959. echo shar: extracting "'year.cursor'" '(256 characters)'
  2960. if test -f 'year.cursor'
  2961. then
  2962.     echo shar: will not over-write existing file "'year.cursor'"
  2963. else
  2964. sed 's/^    X//' << \SHAR_EOF > 'year.cursor'
  2965.     X/* $Header: year.cursor,v 2.1 89/05/09 14:31:12 billr Exp $ */
  2966.     X/* Format_version=1, Width=16, Height=16, Depth=1, Valid_bits_per_item=16
  2967.     X */
  2968.     X    0xFFFF,0xC003,0x8AA9,0x8001,0xFFFF,0xFFFF,0x9249,0xFFFF,
  2969.     X    0x9249,0xFFFF,0x9249,0xFFFF,0x9249,0xFFFF,0x9249,0xFFFF
  2970. SHAR_EOF
  2971. if test 256 -ne "`wc -c < 'year.cursor'`"
  2972. then
  2973.     echo shar: error transmitting "'year.cursor'" '(should have been 256 characters)'
  2974. fi
  2975. fi # end of overwriting check
  2976. echo shar: extracting "'ypaint.c'" '(7772 characters)'
  2977. if test -f 'ypaint.c'
  2978. then
  2979.     echo shar: will not over-write existing file "'ypaint.c'"
  2980. else
  2981. sed 's/^    X//' << \SHAR_EOF > 'ypaint.c'
  2982.     X/*
  2983.     X * $Header: ypaint.c,v 2.1 89/05/09 14:20:15 billr Exp $
  2984.     X */
  2985.     X/*
  2986.     X * ypaint.c
  2987.     X *
  2988.     X * Author: Bill Randle, Tektronix, Inc. <billr@saab.CNA.TEK.COM>
  2989.     X *
  2990.     X * Copyright (C) 1988, 1989 Tektronix, Inc.  All Rights Reserved
  2991.     X *
  2992.     X * Permission is hereby granted to use and modify this code in source
  2993.     X * or binary form as long as it is not sold for profit and this copyright
  2994.     X * notice remains intact.
  2995.     X */
  2996.     X/***************************************************
  2997.     X *                           *
  2998.     X *    Artistic routines that draw in the main    *
  2999.     X * subwindow for the year display.           *
  3000.     X *                           *
  3001.     X ***************************************************/
  3002.     X
  3003.     X#include <suntool/sunview.h>
  3004.     X#include <suntool/canvas.h>
  3005.     X#include <ctype.h>
  3006.     X#include <stdio.h>
  3007.     X#include "ct.h"
  3008.     X#include "paint.h"
  3009.     X
  3010.     X/*
  3011.     X * draw calendar for a whole year.
  3012.     X */
  3013.     Xdraw_year()
  3014.     X{
  3015.     X    int monthnr, daynr, boxnr, i, j, k, thismonth;
  3016.     X    int row, col, x, y;
  3017.     X    int busy_today[366], startbox, nrdays, yrday, extra_days;
  3018.     X    char title[5], c[3], buf[100];
  3019.     X    Rect *rect;
  3020.     X    struct tm Save;
  3021.     X    struct appt_entry appt;
  3022.     X    int read_stat;
  3023.     X    FILE *apts;
  3024.     X
  3025.     X    lock_cursors();
  3026.     X    /* destory future appts popup, if it exists */
  3027.     X    if (fframe) {
  3028.     X        window_destroy(fframe);
  3029.     X        fframe = 0;
  3030.     X    }
  3031.     X    fix_current_day();
  3032.     X
  3033.     X    working(TRUE);
  3034.     X    pw_batch_on(main_pixwin);
  3035.     X    rect = (Rect *) window_get(canvas, WIN_RECT);
  3036.     X    /* Erase the window */
  3037.     X    pw_writebackground(main_pixwin,0,0,rect->r_width,rect->r_height,PIX_CLR);
  3038.     X    startx = (rect->r_width - 3*8*ybox_width)/2 + font->pf_defaultsize.x+1;
  3039.     X    starty = (rect->r_height - 4*7*ybox_height) / 2;
  3040.     X    sun_moon_buttons(FALSE);
  3041.     X    print_button(TRUE);
  3042.     X
  3043.     X    /* Which days have appointments? */
  3044.     X    for (i=0; i<dysize(current.tm_year + 1900); i++)
  3045.     X        busy_today[i] = 0;
  3046.     X    Save = current;
  3047.     X    current.tm_mon = JAN;
  3048.     X    current.tm_mday = 1;
  3049.     X    fix_current_day();
  3050.     X    First = current;
  3051.     X    current.tm_mon = DEC;
  3052.     X    current.tm_mday = monthlength(DEC);
  3053.     X    fix_current_day();
  3054.     X    Last = current;
  3055.     X    if ((apts = fopen(apts_pathname, "r")) == NULL)
  3056.     X        err_rpt("can't open appointments file", FATAL);
  3057.     X
  3058.     X    working(FALSE);
  3059.     X    while ((read_stat = get_aentry(apts, &appt)) != EOF) {
  3060.     X        if (read_stat)
  3061.     X            continue;    /* read error */
  3062.     X        if (appt.flags & A_COMMENT)
  3063.     X            continue;
  3064.     X        if ((appt.flags & MARKED_NOTE) == MARKED_NOTE)
  3065.     X            continue;
  3066.     X        current.tm_year = appt.year;
  3067.     X        current.tm_mon = appt.month;
  3068.     X        current.tm_mday = appt.day;
  3069.     X        if (appt.flags & ALL_YEARS)
  3070.     X            current.tm_year = First.tm_year;
  3071.     X        if (current.tm_year == First.tm_year) {
  3072.     X            if (appt.flags & ALL_MONTHS) {
  3073.     X                for (current.tm_mon = JAN; 
  3074.     X                    current.tm_mon <= DEC; 
  3075.     X                    current.tm_mon++) {
  3076.     X                    if (appt.flags & ALL_DAYS) {
  3077.     X                        for (current.tm_mday = 1; current.tm_mday <= monthlength(current.tm_mon); current.tm_mday++) {
  3078.     X                            fix_current_day();
  3079.     X                            busy_today[current.tm_yday]++;
  3080.     X                        }
  3081.     X                    } else if (appt.flags & EVERY_SOMEDAY) {
  3082.     X                        i = Pickday(appt.flags);
  3083.     X                        for (current.tm_mday = 1; current.tm_mday <= monthlength(current.tm_mon); current.tm_mday++) {
  3084.     X                            fix_current_day();
  3085.     X                            if (current.tm_wday == i)
  3086.     X                                if (chk_week(appt.repeat, current.tm_mday))
  3087.     X                                    busy_today[current.tm_yday]++;
  3088.     X                        }
  3089.     X                    } else {
  3090.     X                        fix_current_day();
  3091.     X                        busy_today[current.tm_yday]++;
  3092.     X                    }
  3093.     X                }
  3094.     X            } else if (appt.flags & REPEAT) {
  3095.     X                if (appt.flags & EVERY_SOMEDAY) {
  3096.     X                    i = Pickday(appt.flags);
  3097.     X                    current.tm_mday = 1;
  3098.     X                    fix_current_day();
  3099.     X                    while (current.tm_wday != i) {
  3100.     X                        current.tm_mday++;
  3101.     X                        current.tm_wday = (current.tm_wday + 1) % 7;
  3102.     X                    }
  3103.     X                    fix_current_day();
  3104.     X                    while (ymd_compare(current, Last) <= 0) {
  3105.     X                        if (chk_week(appt.repeat, current.tm_mday))
  3106.     X                            busy_today[current.tm_yday]++;
  3107.     X                        current.tm_mday += 7;
  3108.     X                        fix_current_day();
  3109.     X                        if (current.tm_mon != appt.month)
  3110.     X                            break;
  3111.     X                    }
  3112.     X                } else {
  3113.     X                    fix_current_day();
  3114.     X                    while (ymd_compare(current, Last) <= 0) {
  3115.     X                        busy_today[current.tm_yday]++;
  3116.     X                        current.tm_mday += appt.repeat;
  3117.     X                        fix_current_day();
  3118.     X                    }
  3119.     X                }
  3120.     X            } else {
  3121.     X                fix_current_day();
  3122.     X                if (appt.flags & DELETED)
  3123.     X                    busy_today[current.tm_yday]--;
  3124.     X                else
  3125.     X                    busy_today[current.tm_yday]++;
  3126.     X            }
  3127.     X        } else if ((appt.flags & REPEAT) && !(appt.flags & EVERY_SOMEDAY)) {
  3128.     X            /* find 1st appt in this year */
  3129.     X            while (ymd_compare(current, First) < 0) {
  3130.     X                current.tm_mday += appt.repeat;
  3131.     X                fix_current_day();
  3132.     X            }
  3133.     X            while (ymd_compare(current, Last) <= 0) {
  3134.     X                busy_today[current.tm_yday]++;
  3135.     X                current.tm_mday += appt.repeat;
  3136.     X                fix_current_day();
  3137.     X            }
  3138.     X        }
  3139.     X
  3140.     X    }
  3141.     X    fclose(apts);
  3142.     X    current = First;
  3143.     X    fix_current_day();
  3144.     X#ifndef NO_HOLIDAYS
  3145.     X    /*
  3146.     X     * now that we've gone thru the appointments file,
  3147.     X     * check to see if the user has selected any holiday
  3148.     X     * options and add them in.
  3149.     X     */
  3150.     X    for (i=0; i<dysize(current.tm_year + 1900); i++) {
  3151.     X        working(TRUE);
  3152.     X        if (holiday_a == 1 && a_dates(&appt, holiday_a))
  3153.     X            busy_today[i]++;
  3154.     X        if (holiday_c == 1 && c_dates(&appt, holiday_c))
  3155.     X            busy_today[i]++;
  3156.     X        working(FALSE);
  3157.     X        if (holiday_i == 1 && i_dates(&appt, holiday_i))
  3158.     X            busy_today[i]++;
  3159.     X        working(TRUE);
  3160.     X        if (holiday_j == 1 && j_dates(&appt, holiday_j))
  3161.     X            busy_today[i]++;
  3162.     X        if (holiday_s == 1 && s_dates(&appt, holiday_s))
  3163.     X            busy_today[i]++;
  3164.     X        current.tm_mday++;
  3165.     X        fix_current_day();
  3166.     X        working(FALSE);
  3167.     X    }
  3168.     X    current = First;
  3169.     X    fix_current_day();
  3170.     X#endif    /* NO_HOLIDAYS */
  3171.     X
  3172.     X    /* display year title */
  3173.     X    sprintf(title, "%d", 1900 + First.tm_year);
  3174.     X    pw_text(main_pixwin, (rect->r_width - bigfont->pf_defaultsize.x*strlen(title))/2, starty - bigfont->pf_defaultsize.y,
  3175.     X      PIX_SRC, bigfont, title);
  3176.     X
  3177.     X    /* display day names */
  3178.     X    strcpy(buf, "Su Mo Tu We Th Fr Sa    ");
  3179.     X    strcat(buf, "Su Mo Tu We Th Fr Sa    ");
  3180.     X    strcat(buf, "Su Mo Tu We Th Fr Sa");
  3181.     X    pw_text(main_pixwin, startx+4, starty-2, PIX_SRC, font, buf);
  3182.     X
  3183.     X    /* draw months */
  3184.     X    monthnr = 0;
  3185.     X    yrday = 0;
  3186.     X    extra_days = 0;
  3187.     X    startbox = First.tm_wday;
  3188.     X    for (row=0; row<4; row++) {
  3189.     X        for (col=0; col<3; col++) {
  3190.     X            x = startx + 8*ybox_width*col;
  3191.     X            y = starty + 7*ybox_height*row;
  3192.     X            mboxlims[monthnr].lowx = x;
  3193.     X            mboxlims[monthnr].lowy = y;
  3194.     X            mboxlims[monthnr].highx = x + 7*ybox_width;
  3195.     X            mboxlims[monthnr].highy = y + 6*ybox_width;
  3196.     X            /* draw month box and label */
  3197.     X            pw_write(main_pixwin, x, y, 7*ybox_width, 
  3198.     X                ybox_height, PIX_SRC, ymonthbox_pr, 0, 0);
  3199.     X            pw_text(main_pixwin, x+8, y+font->pf_defaultsize.y, PIX_SRC, font, 
  3200.     X                monthnames[row*3 + col]);
  3201.     X            if (!extra_days) {
  3202.     X                nrdays = monthlength(monthnr);
  3203.     X                daynr = 1;
  3204.     X            }
  3205.     X            boxnr = 0;
  3206.     X            for (j=0; j<5; j++) {
  3207.     X                y += ybox_height;
  3208.     X                /* foreach week in the month */
  3209.     X                for (k=0; k<7; k++) {
  3210.     X                    /* foreach day in the week */
  3211.     X                    /* draw day boxes */
  3212.     X                    pw_write(main_pixwin, x, y, ybox_width, ybox_height, PIX_SRC, ydaybox_pr, 0, 0);
  3213.     X                    /* label day boxes */
  3214.     X                    if (boxnr >= startbox && daynr <= nrdays) {
  3215.     X                        if (ymd_compare(today, current) == 0)
  3216.     X                            /* gray box */
  3217.     X                            pw_write(main_pixwin, x, y, ybox_width, ybox_height, PIX_SRC, ydaybox_td_pr, 0, 0);
  3218.     X                        c[0] = (daynr<10 ? ' ' : daynr/10 + '0');
  3219.     X                        c[1] = daynr%10 + '0';
  3220.     X                        c[2] = '\0';
  3221.     X                        pw_text(main_pixwin, x+4, y+14,
  3222.     X                          PIX_SRC|PIX_DST, font, c);
  3223.     X                        /* if appointment exists, reverse video box */
  3224.     X                        if (busy_today[yrday] > 0)
  3225.     X                            pw_write(main_pixwin, x+2, y+2,
  3226.     X                              ybox_width-4, ybox_height-4,
  3227.     X                              PIX_NOT(PIX_DST), NULL, 0, 0);
  3228.     X                        if (daynr == nrdays)
  3229.     X                            startbox = (k + 1) % 7;
  3230.     X                        ++daynr;
  3231.     X                        ++yrday;
  3232.     X                        current.tm_mday++;
  3233.     X                        fix_current_day();
  3234.     X                    }
  3235.     X                    x += ybox_width;
  3236.     X                    ++boxnr;
  3237.     X                    if (extra_days && daynr > nrdays) {
  3238.     X                        /* time to start new month */
  3239.     X                        extra_days = 0;
  3240.     X                        nrdays = monthlength(monthnr);
  3241.     X                        daynr = 1;
  3242.     X                    }
  3243.     X                }
  3244.     X                x -= 7*ybox_width;
  3245.     X            }
  3246.     X            if (daynr <= nrdays) {
  3247.     X                /* leftover goes in next month */
  3248.     X                extra_days++;
  3249.     X                startbox = 0;
  3250.     X            }
  3251.     X            ++monthnr;
  3252.     X        }
  3253.     X    }
  3254.     X    pw_batch_off(main_pixwin);
  3255.     X    current = Save;
  3256.     X    fix_current_day();
  3257.     X    unlock_cursors();
  3258.     X}
  3259.     X
  3260. SHAR_EOF
  3261. if test 7772 -ne "`wc -c < 'ypaint.c'`"
  3262. then
  3263.     echo shar: error transmitting "'ypaint.c'" '(should have been 7772 characters)'
  3264. fi
  3265. fi # end of overwriting check
  3266. #    End of shell archive
  3267. exit 0
  3268.